InterpAsm-x86.S revision 7dc44a1c9a37d528f080eb51739da80696bb1f05
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,sReg0                 # we'll need the desired class on failure
6560    movl    %eax,OUT_ARG1(%esp)
6561    movl    %ecx,OUT_ARG0(%esp)
6562    call    dvmInstanceofNonTrivial    # eax<- boolean result
6563    testl   %eax,%eax                  # failed?
6564    jne     .LOP_CHECK_CAST_okay           # no, success
6565
6566    # A cast has failed.  We need to throw a ClassCastException.
6567    EXPORT_PC
6568    movl    offObject_clazz(rINST),%eax
6569    movl    %eax,OUT_ARG0(%esp)                 # arg0<- obj->clazz
6570    movl    sReg0,%ecx
6571    movl    %ecx,OUT_ARG1(%esp)                 # arg1<- desired class
6572    call    dvmThrowClassCastException
6573    jmp     common_exceptionThrown
6574
6575    /*
6576     * Resolution required.  This is the least-likely path, and we're
6577     * going to have to recreate some data.
6578     *
6579     *  rINST holds object
6580     */
6581.LOP_CHECK_CAST_resolve:
6582    movl    rGLUE,%ecx
6583    EXPORT_PC
6584    movzwl  2(rPC),%eax                # eax<- BBBB
6585    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6586    movl    %eax,OUT_ARG1(%esp)        # arg1<- BBBB
6587    movl    offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6588    movl    $0,OUT_ARG2(%esp)         # arg2<- false
6589    movl    %ecx,OUT_ARG0(%esp)        # arg0<- method->clazz
6590    call    dvmResolveClass            # eax<- resolved ClassObject ptr
6591    testl   %eax,%eax                  # got null?
6592    je      common_exceptionThrown     # yes, handle exception
6593    movl    offObject_clazz(rINST),%ecx  # ecx<- obj->clazz
6594    jmp     .LOP_CHECK_CAST_resolved       # pick up where we left off
6595
6596/* continuation for OP_INSTANCE_OF */
6597
6598    /*
6599     * Trivial test failed, need to perform full check.  This is common.
6600     *  eax holds obj->clazz
6601     *  ecx holds class resolved from BBBB
6602     *  rINST has BA
6603     */
6604.LOP_INSTANCE_OF_fullcheck:
6605    movl    %eax,OUT_ARG0(%esp)
6606    movl    %ecx,OUT_ARG1(%esp)
6607    call    dvmInstanceofNonTrivial     # eax<- boolean result
6608    # fall through to OP_INSTANCE_OF_store
6609
6610    /*
6611     * eax holds boolean result
6612     * rINST holds BA
6613     */
6614.LOP_INSTANCE_OF_store:
6615    FETCH_INST_OPCODE 2 %edx
6616    andb    $0xf,rINSTbl               # <- A
6617    ADVANCE_PC 2
6618    SET_VREG %eax rINST                 # vA<- eax
6619    GOTO_NEXT_R %edx
6620
6621    /*
6622     * Trivial test succeeded, save and bail.
6623     *  r9 holds A
6624     */
6625.LOP_INSTANCE_OF_trivial:
6626    FETCH_INST_OPCODE 2 %edx
6627    andb    $0xf,rINSTbl               # <- A
6628    ADVANCE_PC 2
6629    movl    $1,%eax
6630    SET_VREG %eax rINST                 # vA<- true
6631    GOTO_NEXT_R %edx
6632
6633    /*
6634     * Resolution required.  This is the least-likely path.
6635     *
6636     *  edx holds BBBB
6637     *  rINST holds BA
6638     */
6639.LOP_INSTANCE_OF_resolve:
6640    movl    %edx,OUT_ARG1(%esp)         # arg1<- BBBB
6641    movl    rGLUE,%ecx
6642    movl    offGlue_method(%ecx),%ecx
6643    movl    $1,OUT_ARG2(%esp)          # arg2<- true
6644    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6645    EXPORT_PC
6646    movl    %ecx,OUT_ARG0(%esp)         # arg0<- method->clazz
6647    call    dvmResolveClass             # eax<- resolved ClassObject ptr
6648    testl   %eax,%eax                   # success?
6649    je      common_exceptionThrown      # no, handle exception
6650/* Now, we need to sync up with fast path.  We need eax to
6651 * hold the obj->clazz, and ecx to hold the resolved class
6652 */
6653    movl    %eax,%ecx                   # ecx<- resolved class
6654    movl    rINST,%eax                # eax<- BA
6655    sarl    $4,%eax                    # eax<- B
6656    GET_VREG_R %eax %eax                # eax<- vB (obj)
6657    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
6658    jmp     .LOP_INSTANCE_OF_resolved
6659
6660/* continuation for OP_NEW_INSTANCE */
6661
6662.LOP_NEW_INSTANCE_initialized:  # on entry, ecx<- class
6663    /* TODO: remove test for interface/abstract, now done in verifier */
6664    testl     $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6665    movl      $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6666    jne       .LOP_NEW_INSTANCE_abstract
6667.LOP_NEW_INSTANCE_finish: # ecx=class
6668    movl     %ecx,OUT_ARG0(%esp)
6669    call     dvmAllocObject             # eax<- new object
6670    FETCH_INST_OPCODE 2 %edx
6671    testl    %eax,%eax                  # success?
6672    je       common_exceptionThrown     # no, bail out
6673    SET_VREG %eax rINST
6674    ADVANCE_PC 2
6675    GOTO_NEXT_R %edx
6676
6677    /*
6678     * Class initialization required.
6679     *
6680     *  ecx holds class object
6681     */
6682.LOP_NEW_INSTANCE_needinit:
6683    SPILL_TMP1(%ecx)                    # save object
6684    movl    %ecx,OUT_ARG0(%esp)
6685    call    dvmInitClass                # initialize class
6686    UNSPILL_TMP1(%ecx)                  # restore object
6687    testl   %eax,%eax                   # success?
6688    jne     .LOP_NEW_INSTANCE_initialized     # success, continue
6689    jmp     common_exceptionThrown      # go deal with init exception
6690
6691    /*
6692     * Resolution required.  This is the least-likely path.
6693     *
6694     */
6695.LOP_NEW_INSTANCE_resolve:
6696    movl    rGLUE,%ecx
6697    movzwl  2(rPC),%eax
6698    movl    offGlue_method(%ecx),%ecx   # ecx<- glue->method
6699    movl    %eax,OUT_ARG1(%esp)
6700    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6701    movl    $0,OUT_ARG2(%esp)
6702    movl    %ecx,OUT_ARG0(%esp)
6703    call    dvmResolveClass             # call(clazz,off,flags)
6704    movl    %eax,%ecx                   # ecx<- resolved ClassObject ptr
6705    testl   %ecx,%ecx                   # success?
6706    jne     .LOP_NEW_INSTANCE_resolved        # good to go
6707    jmp     common_exceptionThrown      # no, handle exception
6708
6709    /*
6710     * TODO: remove this
6711     * We can't instantiate an abstract class or interface, so throw an
6712     * InstantiationError with the class descriptor as the message.
6713     *
6714     *  ecx holds class object
6715     */
6716.LOP_NEW_INSTANCE_abstract:
6717    movl    offClassObject_descriptor(%ecx),%eax
6718    movl    $.LstrInstantiationError,OUT_ARG0(%esp)
6719    movl    %eax,OUT_ARG1(%esp)
6720    call    dvmThrowExceptionWithClassMessage
6721    jmp     common_exceptionThrown
6722
6723/* continuation for OP_NEW_ARRAY */
6724
6725    /*
6726     * Resolve class.  (This is an uncommon case.)
6727     *  ecx holds class (null here)
6728     *  eax holds array length (vB)
6729     */
6730.LOP_NEW_ARRAY_resolve:
6731    movl    rGLUE,%ecx
6732    SPILL_TMP1(%eax)                   # save array length
6733    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6734    movzwl  2(rPC),%eax                # eax<- CCCC
6735    movl    offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6736    movl    %eax,OUT_ARG1(%esp)
6737    movl    $0,OUT_ARG2(%esp)
6738    movl    %ecx,OUT_ARG0(%esp)
6739    call    dvmResolveClass            # eax<- call(clazz,ref,flag)
6740    movl    %eax,%ecx
6741    UNSPILL_TMP1(%eax)
6742    testl   %ecx,%ecx                  # successful resolution?
6743    je      common_exceptionThrown     # no, bail.
6744# fall through to OP_NEW_ARRAY_finish
6745
6746    /*
6747     * Finish allocation
6748     *
6749     * ecx holds class
6750     * eax holds array length (vB)
6751     */
6752.LOP_NEW_ARRAY_finish:
6753    movl    %ecx,OUT_ARG0(%esp)
6754    movl    %eax,OUT_ARG1(%esp)
6755    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6756    call    dvmAllocArrayByClass    # eax<- call(clazz,length,flags)
6757    FETCH_INST_OPCODE 2 %edx
6758    testl   %eax,%eax               # failed?
6759    je      common_exceptionThrown  # yup - go handle
6760    SET_VREG %eax rINST
6761    ADVANCE_PC 2
6762    GOTO_NEXT_R %edx
6763
6764/* continuation for OP_FILLED_NEW_ARRAY */
6765
6766.LOP_FILLED_NEW_ARRAY_more:
6767    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6768    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6769    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6770    testl   %eax,%eax                         # null?
6771    je      common_exceptionThrown            # yes, handle it
6772
6773       # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6774
6775    /*
6776     * On entry:
6777     *    eax holds array class [r0]
6778     *    rINST holds AA or BB [r10]
6779     *    ecx is scratch
6780     */
6781.LOP_FILLED_NEW_ARRAY_continue:
6782    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6783    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6784    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6785    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6786    movl    rGLUE,%eax
6787    cmpb    $'I',%cl                             # supported?
6788    je      1f
6789    cmpb    $'L',%cl
6790    je      1f
6791    cmpb    $'[',%cl
6792    jne      .LOP_FILLED_NEW_ARRAY_notimpl                  # no, not handled yet
67931:
6794    movl    %ecx,offGlue_retval+4(%eax)           # save type
6795    .if      (!0)
6796    SPILL_TMP1(rINST)                              # save copy, need "B" later
6797    sarl    $4,rINST
6798    .endif
6799    movl    rINST,OUT_ARG1(%esp)                  # arg1<- A or AA (length)
6800    call    dvmAllocArrayByClass     # eax<- call(arrayClass, length, flags)
6801    movl    rGLUE,%ecx
6802    testl   %eax,%eax                             # alloc successful?
6803    je      common_exceptionThrown                # no, handle exception
6804    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6805    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6806    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6807
6808/* at this point:
6809 *     eax is pointer to tgt
6810 *     rINST is length
6811 *     ecx is FEDC or CCCC
6812 *     TMP_SPILL1 is BA
6813 *  We now need to copy values from registers into the array
6814 */
6815
6816    .if 0
6817    # set up src pointer
6818    SPILL_TMP2(%esi)
6819    SPILL_TMP3(%edi)
6820    leal    (rFP,%ecx,4),%esi # set up src ptr
6821    movl    %eax,%edi         # set up dst ptr
6822    movl    rINST,%ecx        # load count register
6823    rep
6824    movsd
6825    UNSPILL_TMP2(%esi)
6826    UNSPILL_TMP3(%edi)
6827    movl    rGLUE,%ecx
6828    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6829    FETCH_INST_OPCODE 3 %edx
6830    .else
6831    testl  rINST,rINST
6832    je     4f
6833    UNSPILL_TMP1(%edx)        # restore "BA"
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_SPILL1 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    leal    (rFP,%ecx,4),%esi # set up src ptr
6932    movl    %eax,%edi         # set up dst 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    UNSPILL_TMP1(%edx)        # restore "BA"
6945    andl   $0x0f,%edx        # edx<- 0000000A
6946    sall   $16,%edx          # edx<- 000A0000
6947    orl    %ecx,%edx          # edx<- 000AFEDC
69483:
6949    movl   $0xf,%ecx
6950    andl   %edx,%ecx          # ecx<- next reg to load
6951    GET_VREG_R %ecx %ecx
6952    shrl   $4,%edx
6953    leal   4(%eax),%eax
6954    movl   %ecx,-4(%eax)
6955    sub    $1,rINST
6956    jne    3b
69574:
6958    movl   rGLUE,%ecx
6959    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6960    FETCH_INST_OPCODE 3 %edx
6961    .endif
6962
6963    cmpb    $'I',%al                        # Int array?
6964    je      5f                               # skip card mark if so
6965    movl    offGlue_retval(%ecx),%eax        # eax<- object head
6966    movl    offGlue_cardTable(%ecx),%ecx     # card table base
6967    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
6968    movb    %cl,(%ecx,%eax)                  # mark card based on object head
69695:
6970    ADVANCE_PC 3
6971    GOTO_NEXT_R %edx
6972
6973
6974    /*
6975     * Throw an exception indicating that we have not implemented this
6976     * mode of filled-new-array.
6977     */
6978.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6979    movl    $.LstrInternalErrorA,%eax
6980    movl    %eax,OUT_ARG0(%esp)
6981    movl    $.LstrFilledNewArrayNotImplA,%eax
6982    movl    %eax,OUT_ARG1(%esp)
6983    call    dvmThrowException
6984    jmp     common_exceptionThrown
6985
6986/* continuation for OP_CMPL_FLOAT */
6987
6988.LOP_CMPL_FLOAT_isNaN:
6989    movl      $-1,%ecx
6990    jmp       .LOP_CMPL_FLOAT_finish
6991
6992/* continuation for OP_CMPG_FLOAT */
6993
6994.LOP_CMPG_FLOAT_isNaN:
6995    movl      $1,%ecx
6996    jmp       .LOP_CMPG_FLOAT_finish
6997
6998/* continuation for OP_CMPL_DOUBLE */
6999
7000.LOP_CMPL_DOUBLE_isNaN:
7001    movl      $-1,%ecx
7002    jmp       .LOP_CMPL_DOUBLE_finish
7003
7004/* continuation for OP_CMPG_DOUBLE */
7005
7006.LOP_CMPG_DOUBLE_isNaN:
7007    movl      $1,%ecx
7008    jmp       .LOP_CMPG_DOUBLE_finish
7009
7010/* continuation for OP_CMP_LONG */
7011
7012.LOP_CMP_LONG_bigger:
7013    movl      $1,%ecx
7014    jmp       .LOP_CMP_LONG_finish
7015.LOP_CMP_LONG_smaller:
7016    movl      $-1,%ecx
7017.LOP_CMP_LONG_finish:
7018    SET_VREG %ecx rINST
7019    FETCH_INST_OPCODE 2 %edx
7020    ADVANCE_PC 2
7021    GOTO_NEXT_R %edx
7022
7023/* continuation for OP_AGET_WIDE */
7024
7025.LOP_AGET_WIDE_finish:
7026    leal      offArrayObject_contents(%eax,%ecx,8),%eax
7027    movl      (%eax),%ecx
7028    movl      4(%eax),%eax
7029    SET_VREG_WORD %ecx rINST 0
7030    SET_VREG_WORD %eax rINST 1
7031    FETCH_INST_OPCODE 2 %edx
7032    ADVANCE_PC 2
7033    GOTO_NEXT_R %edx
7034
7035/* continuation for OP_APUT_WIDE */
7036
7037.LOP_APUT_WIDE_finish:
7038    leal      offArrayObject_contents(%eax,%ecx,8),%eax
7039    GET_VREG_WORD %ecx rINST 0
7040    GET_VREG_WORD rINST rINST 1
7041    movl      rINST,4(%eax)
7042    FETCH_INST_OPCODE 2 %edx
7043    movl      %ecx,(%eax)
7044    ADVANCE_PC 2
7045    GOTO_NEXT_R %edx
7046
7047/* continuation for OP_APUT_OBJECT */
7048
7049    /* On entry:
7050     *   eax<- array object
7051     *   ecx<- index
7052     *   rINST<- vAA
7053     */
7054.LOP_APUT_OBJECT_continue:
7055    leal      offArrayObject_contents(%eax,%ecx,4),%ecx
7056    testl     rINST,rINST                    # storing null reference?
7057    je        .LOP_APUT_OBJECT_skip_check
7058    SPILL_TMP1(%ecx)                         # save target address
7059    SPILL_TMP2(%eax)                         # save object head
7060    movl      offObject_clazz(%eax),%eax     # eax<- arrayObj->clazz
7061    movl      offObject_clazz(rINST),%ecx    # ecx<- obj->clazz
7062    movl      %eax,OUT_ARG1(%esp)
7063    movl      %ecx,OUT_ARG0(%esp)
7064    movl      %ecx,sReg0                     # store the two classes for later
7065    movl      %eax,sReg1
7066    call      dvmCanPutArrayElement          # test object type vs. array type
7067    UNSPILL_TMP1(%ecx)                       # recover target address
7068    testl     %eax,%eax
7069    movl      rGLUE,%eax
7070    jne       .LOP_APUT_OBJECT_types_okay
7071
7072    # The types don't match.  We need to throw an ArrayStoreException.
7073    EXPORT_PC
7074    movl      sReg0,%eax                     # restore the two classes...
7075    movl      %eax,OUT_ARG0(%esp)
7076    movl      sReg1,%ecx
7077    movl      %ecx,OUT_ARG1(%esp)
7078    call      dvmThrowArrayStoreException    # ...and throw
7079    jmp       common_exceptionThrown
7080
7081.LOP_APUT_OBJECT_types_okay:
7082    movl      offGlue_cardTable(%eax),%eax   # get card table base
7083    movl      rINST,(%ecx)                   # store into array
7084    UNSPILL_TMP2(%ecx)                       # recover object head
7085    FETCH_INST_OPCODE 2 %edx
7086    shrl      $GC_CARD_SHIFT,%ecx           # object head to card number
7087    movb      %al,(%eax,%ecx)                # mark card using object head
7088    ADVANCE_PC 2
7089    GOTO_NEXT_R %edx
7090
7091.LOP_APUT_OBJECT_skip_check:
7092    movl      rINST,(%ecx)
7093    FETCH_INST_OPCODE 2 %edx
7094    ADVANCE_PC 2
7095    GOTO_NEXT_R %edx
7096
7097/* continuation for OP_IGET */
7098
7099
7100.LOP_IGET_resolve:
7101    EXPORT_PC
7102    movl    offGlue_method(%edx),%edx           # edx<- current method
7103    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7104    SPILL_TMP1(%ecx)                            # save obj pointer across call
7105    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7106    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7107    UNSPILL_TMP1(%ecx)
7108    testl   %eax,%eax                           #  returns InstrField ptr
7109    jne     .LOP_IGET_finish
7110    jmp     common_exceptionThrown
7111
7112.LOP_IGET_finish:
7113    /*
7114     * Currently:
7115     *   eax holds resolved field
7116     *   ecx holds object
7117     *   rINST holds A
7118     */
7119    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7120    testl   %ecx,%ecx                           # object null?
7121    je      common_errNullObject                # object was null
7122    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7123    movl    rINST,%eax                          # eax<- A
7124    FETCH_INST_OPCODE 2 %edx
7125    SET_VREG %ecx %eax
7126    ADVANCE_PC 2
7127    GOTO_NEXT_R %edx
7128
7129/* continuation for OP_IGET_WIDE */
7130
7131
7132.LOP_IGET_WIDE_resolve:
7133    EXPORT_PC
7134    movl    offGlue_method(%edx),%edx           # edx<- current method
7135    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7136    SPILL_TMP1(%ecx)                            # save objpointer across call
7137    movl    rPC,OUT_ARG0(%esp)                  # pass in method->clazz
7138    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7139    UNSPILL_TMP1(%ecx)
7140    testl   %eax,%eax                           # returns InstrField ptr
7141    jne     .LOP_IGET_WIDE_finish
7142    jmp     common_exceptionThrown
7143
7144.LOP_IGET_WIDE_finish:
7145    /*
7146     * Currently:
7147     *   eax holds resolved field
7148     *   ecx holds object
7149     *   rINST holds A
7150     */
7151    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7152    testl   %ecx,%ecx                           # object null?
7153    je      common_errNullObject                # object was null
7154    leal    (%ecx,%eax,1),%eax                  # eax<- address of field
7155    movl    (%eax),%ecx                         # ecx<- lsw
7156    movl    4(%eax),%eax                        # eax<- msw
7157    FETCH_INST_OPCODE 2 %edx
7158    SET_VREG_WORD %ecx rINST 0
7159    SET_VREG_WORD %eax rINST 1
7160    ADVANCE_PC 2
7161    GOTO_NEXT_R %edx
7162
7163/* continuation for OP_IGET_OBJECT */
7164
7165
7166.LOP_IGET_OBJECT_resolve:
7167    EXPORT_PC
7168    movl    offGlue_method(%edx),%edx           # edx<- current method
7169    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7170    SPILL_TMP1(%ecx)                            # save obj pointer across call
7171    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7172    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7173    UNSPILL_TMP1(%ecx)
7174    testl   %eax,%eax                           #  returns InstrField ptr
7175    jne     .LOP_IGET_OBJECT_finish
7176    jmp     common_exceptionThrown
7177
7178.LOP_IGET_OBJECT_finish:
7179    /*
7180     * Currently:
7181     *   eax holds resolved field
7182     *   ecx holds object
7183     *   rINST holds A
7184     */
7185    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7186    testl   %ecx,%ecx                           # object null?
7187    je      common_errNullObject                # object was null
7188    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7189    movl    rINST,%eax                          # eax<- A
7190    FETCH_INST_OPCODE 2 %edx
7191    SET_VREG %ecx %eax
7192    ADVANCE_PC 2
7193    GOTO_NEXT_R %edx
7194
7195/* continuation for OP_IGET_BOOLEAN */
7196
7197
7198.LOP_IGET_BOOLEAN_resolve:
7199    EXPORT_PC
7200    movl    offGlue_method(%edx),%edx           # edx<- current method
7201    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7202    SPILL_TMP1(%ecx)                            # save obj pointer across call
7203    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7204    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7205    UNSPILL_TMP1(%ecx)
7206    testl   %eax,%eax                           #  returns InstrField ptr
7207    jne     .LOP_IGET_BOOLEAN_finish
7208    jmp     common_exceptionThrown
7209
7210.LOP_IGET_BOOLEAN_finish:
7211    /*
7212     * Currently:
7213     *   eax holds resolved field
7214     *   ecx holds object
7215     *   rINST holds A
7216     */
7217    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7218    testl   %ecx,%ecx                           # object null?
7219    je      common_errNullObject                # object was null
7220    movzbl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7221    movl    rINST,%eax                          # eax<- A
7222    FETCH_INST_OPCODE 2 %edx
7223    SET_VREG %ecx %eax
7224    ADVANCE_PC 2
7225    GOTO_NEXT_R %edx
7226
7227/* continuation for OP_IGET_BYTE */
7228
7229
7230.LOP_IGET_BYTE_resolve:
7231    EXPORT_PC
7232    movl    offGlue_method(%edx),%edx           # edx<- current method
7233    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7234    SPILL_TMP1(%ecx)                            # save obj pointer across call
7235    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7236    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7237    UNSPILL_TMP1(%ecx)
7238    testl   %eax,%eax                           #  returns InstrField ptr
7239    jne     .LOP_IGET_BYTE_finish
7240    jmp     common_exceptionThrown
7241
7242.LOP_IGET_BYTE_finish:
7243    /*
7244     * Currently:
7245     *   eax holds resolved field
7246     *   ecx holds object
7247     *   rINST holds A
7248     */
7249    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7250    testl   %ecx,%ecx                           # object null?
7251    je      common_errNullObject                # object was null
7252    movsbl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7253    movl    rINST,%eax                          # eax<- A
7254    FETCH_INST_OPCODE 2 %edx
7255    SET_VREG %ecx %eax
7256    ADVANCE_PC 2
7257    GOTO_NEXT_R %edx
7258
7259/* continuation for OP_IGET_CHAR */
7260
7261
7262.LOP_IGET_CHAR_resolve:
7263    EXPORT_PC
7264    movl    offGlue_method(%edx),%edx           # edx<- current method
7265    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7266    SPILL_TMP1(%ecx)                            # save obj pointer across call
7267    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7268    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7269    UNSPILL_TMP1(%ecx)
7270    testl   %eax,%eax                           #  returns InstrField ptr
7271    jne     .LOP_IGET_CHAR_finish
7272    jmp     common_exceptionThrown
7273
7274.LOP_IGET_CHAR_finish:
7275    /*
7276     * Currently:
7277     *   eax holds resolved field
7278     *   ecx holds object
7279     *   rINST holds A
7280     */
7281    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7282    testl   %ecx,%ecx                           # object null?
7283    je      common_errNullObject                # object was null
7284    movzwl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7285    movl    rINST,%eax                          # eax<- A
7286    FETCH_INST_OPCODE 2 %edx
7287    SET_VREG %ecx %eax
7288    ADVANCE_PC 2
7289    GOTO_NEXT_R %edx
7290
7291/* continuation for OP_IGET_SHORT */
7292
7293
7294.LOP_IGET_SHORT_resolve:
7295    EXPORT_PC
7296    movl    offGlue_method(%edx),%edx           # edx<- current method
7297    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7298    SPILL_TMP1(%ecx)                            # save obj pointer across call
7299    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
7300    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7301    UNSPILL_TMP1(%ecx)
7302    testl   %eax,%eax                           #  returns InstrField ptr
7303    jne     .LOP_IGET_SHORT_finish
7304    jmp     common_exceptionThrown
7305
7306.LOP_IGET_SHORT_finish:
7307    /*
7308     * Currently:
7309     *   eax holds resolved field
7310     *   ecx holds object
7311     *   rINST holds A
7312     */
7313    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7314    testl   %ecx,%ecx                           # object null?
7315    je      common_errNullObject                # object was null
7316    movswl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
7317    movl    rINST,%eax                          # eax<- A
7318    FETCH_INST_OPCODE 2 %edx
7319    SET_VREG %ecx %eax
7320    ADVANCE_PC 2
7321    GOTO_NEXT_R %edx
7322
7323/* continuation for OP_IPUT */
7324
7325
7326.LOP_IPUT_resolve:
7327    EXPORT_PC
7328    movl    offGlue_method(%edx),%edx           # edx<- current method
7329    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7330    SPILL_TMP1(%ecx)                            # save obj pointer across call
7331    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7332    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7333    UNSPILL_TMP1(%ecx)
7334    testl   %eax,%eax                           # returns InstrField ptr
7335    jne     .LOP_IPUT_finish
7336    jmp     common_exceptionThrown
7337
7338.LOP_IPUT_finish:
7339    /*
7340     * Currently:
7341     *   eax holds resolved field
7342     *   ecx holds object
7343     *   rINST holds A
7344     */
7345    GET_VREG_R rINST rINST                       # rINST<- v[A]
7346    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7347    testl   %ecx,%ecx                            # object null?
7348    je      common_errNullObject                 # object was null
7349    FETCH_INST_OPCODE 2 %edx
7350    movl   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7351    ADVANCE_PC 2
7352    GOTO_NEXT_R %edx
7353
7354/* continuation for OP_IPUT_WIDE */
7355
7356
7357.LOP_IPUT_WIDE_resolve:
7358    EXPORT_PC
7359    movl    offGlue_method(%edx),%edx           # edx<- current method
7360    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7361    SPILL_TMP1(%ecx)                            # save obj pointer across call
7362    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7363    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7364    UNSPILL_TMP1(%ecx)
7365    testl   %eax,%eax                           #  ... which returns InstrField ptr
7366    jne     .LOP_IPUT_WIDE_finish
7367    jmp     common_exceptionThrown
7368
7369.LOP_IPUT_WIDE_finish:
7370    /*
7371     * Currently:
7372     *   eax holds resolved field
7373     *   ecx holds object
7374     *   %edx is scratch, but needs to be unspilled
7375     *   rINST holds A
7376     */
7377    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7378    testl   %ecx,%ecx                           # object null?
7379    je      common_errNullObject                # object was null
7380    leal    (%ecx,%eax,1),%eax                  # eax<- address of field
7381    GET_VREG_WORD %ecx rINST 0                  # ecx<- lsw
7382    GET_VREG_WORD rINST rINST 1                 # rINST<- msw
7383    FETCH_INST_OPCODE 2 %edx
7384    movl    rINST,4(%eax)
7385    movl    %ecx,(%eax)
7386    ADVANCE_PC 2
7387    GOTO_NEXT_R %edx
7388
7389/* continuation for OP_IPUT_OBJECT */
7390
7391
7392.LOP_IPUT_OBJECT_resolve:
7393    EXPORT_PC
7394    movl    offGlue_method(%edx),%edx           # edx<- current method
7395    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7396    SPILL_TMP1(%ecx)                            # save obj pointer across call
7397    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7398    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7399    UNSPILL_TMP1(%ecx)
7400    testl   %eax,%eax                           # returns InstrField ptr
7401    jne     .LOP_IPUT_OBJECT_finish
7402    jmp     common_exceptionThrown
7403
7404.LOP_IPUT_OBJECT_finish:
7405    /*
7406     * Currently:
7407     *   eax holds resolved field
7408     *   ecx holds object
7409     *   %edx is scratch, but needs to be unspilled
7410     *   rINST holds A
7411     */
7412    GET_VREG_R rINST rINST                      # rINST<- v[A]
7413    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
7414    testl   %ecx,%ecx                           # object null?
7415    je      common_errNullObject                # object was null
7416    movl    rINST,(%ecx,%eax)      # obj.field <- v[A](8/16/32 bits)
7417    movl    rGLUE,%eax
7418    testl   rINST,rINST                         # stored a NULL?
7419    movl    offGlue_cardTable(%eax),%eax        # get card table base
7420    FETCH_INST_OPCODE 2 %edx
7421    je      1f                                  # skip card mark if null store
7422    shrl    $GC_CARD_SHIFT,%ecx                # object head to card number
7423    movb    %al,(%eax,%ecx)                     # mark card using object head
74241:
7425    ADVANCE_PC 2
7426    GOTO_NEXT_R %edx
7427
7428/* continuation for OP_IPUT_BOOLEAN */
7429
7430
7431.LOP_IPUT_BOOLEAN_resolve:
7432    EXPORT_PC
7433    movl    offGlue_method(%edx),%edx           # edx<- current method
7434    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7435    SPILL_TMP1(%ecx)                            # save obj pointer across call
7436    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7437    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7438    UNSPILL_TMP1(%ecx)
7439    testl   %eax,%eax                           # returns InstrField ptr
7440    jne     .LOP_IPUT_BOOLEAN_finish
7441    jmp     common_exceptionThrown
7442
7443.LOP_IPUT_BOOLEAN_finish:
7444    /*
7445     * Currently:
7446     *   eax holds resolved field
7447     *   ecx holds object
7448     *   rINST holds A
7449     */
7450    GET_VREG_R rINST rINST                       # rINST<- v[A]
7451    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7452    testl   %ecx,%ecx                            # object null?
7453    je      common_errNullObject                 # object was null
7454    FETCH_INST_OPCODE 2 %edx
7455    movb   rINSTbl,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7456    ADVANCE_PC 2
7457    GOTO_NEXT_R %edx
7458
7459/* continuation for OP_IPUT_BYTE */
7460
7461
7462.LOP_IPUT_BYTE_resolve:
7463    EXPORT_PC
7464    movl    offGlue_method(%edx),%edx           # edx<- current method
7465    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7466    SPILL_TMP1(%ecx)                            # save obj pointer across call
7467    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7468    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7469    UNSPILL_TMP1(%ecx)
7470    testl   %eax,%eax                           # returns InstrField ptr
7471    jne     .LOP_IPUT_BYTE_finish
7472    jmp     common_exceptionThrown
7473
7474.LOP_IPUT_BYTE_finish:
7475    /*
7476     * Currently:
7477     *   eax holds resolved field
7478     *   ecx holds object
7479     *   rINST holds A
7480     */
7481    GET_VREG_R rINST rINST                       # rINST<- v[A]
7482    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7483    testl   %ecx,%ecx                            # object null?
7484    je      common_errNullObject                 # object was null
7485    FETCH_INST_OPCODE 2 %edx
7486    movb   rINSTbl,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7487    ADVANCE_PC 2
7488    GOTO_NEXT_R %edx
7489
7490/* continuation for OP_IPUT_CHAR */
7491
7492
7493.LOP_IPUT_CHAR_resolve:
7494    EXPORT_PC
7495    movl    offGlue_method(%edx),%edx           # edx<- current method
7496    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7497    SPILL_TMP1(%ecx)                            # save obj pointer across call
7498    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7499    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7500    UNSPILL_TMP1(%ecx)
7501    testl   %eax,%eax                           # returns InstrField ptr
7502    jne     .LOP_IPUT_CHAR_finish
7503    jmp     common_exceptionThrown
7504
7505.LOP_IPUT_CHAR_finish:
7506    /*
7507     * Currently:
7508     *   eax holds resolved field
7509     *   ecx holds object
7510     *   rINST holds A
7511     */
7512    GET_VREG_R rINST rINST                       # rINST<- v[A]
7513    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7514    testl   %ecx,%ecx                            # object null?
7515    je      common_errNullObject                 # object was null
7516    FETCH_INST_OPCODE 2 %edx
7517    movw   rINSTw,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7518    ADVANCE_PC 2
7519    GOTO_NEXT_R %edx
7520
7521/* continuation for OP_IPUT_SHORT */
7522
7523
7524.LOP_IPUT_SHORT_resolve:
7525    EXPORT_PC
7526    movl    offGlue_method(%edx),%edx           # edx<- current method
7527    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
7528    SPILL_TMP1(%ecx)                            # save obj pointer across call
7529    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
7530    call    dvmResolveInstField                 #  ... to dvmResolveInstField
7531    UNSPILL_TMP1(%ecx)
7532    testl   %eax,%eax                           # returns InstrField ptr
7533    jne     .LOP_IPUT_SHORT_finish
7534    jmp     common_exceptionThrown
7535
7536.LOP_IPUT_SHORT_finish:
7537    /*
7538     * Currently:
7539     *   eax holds resolved field
7540     *   ecx holds object
7541     *   rINST holds A
7542     */
7543    GET_VREG_R rINST rINST                       # rINST<- v[A]
7544    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7545    testl   %ecx,%ecx                            # object null?
7546    je      common_errNullObject                 # object was null
7547    FETCH_INST_OPCODE 2 %edx
7548    movw   rINSTw,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7549    ADVANCE_PC 2
7550    GOTO_NEXT_R %edx
7551
7552/* continuation for OP_SGET */
7553
7554    /*
7555     * Go resolve the field
7556     */
7557.LOP_SGET_resolve:
7558    movl     rGLUE,%ecx
7559    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7560    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7561    EXPORT_PC                                   # could throw, need to export
7562    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7563    movl     %eax,OUT_ARG1(%esp)
7564    movl     %ecx,OUT_ARG0(%esp)
7565    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7566    testl    %eax,%eax
7567    jne      .LOP_SGET_finish                 # success, continue
7568    jmp      common_exceptionThrown             # no, handle exception
7569
7570/* continuation for OP_SGET_WIDE */
7571
7572    /*
7573     * Go resolve the field
7574     */
7575.LOP_SGET_WIDE_resolve:
7576    movl     rGLUE,%ecx
7577    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7578    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7579    EXPORT_PC                                   # could throw, need to export
7580    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7581    movl     %eax,OUT_ARG1(%esp)
7582    movl     %ecx,OUT_ARG0(%esp)
7583    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7584    testl    %eax,%eax
7585    jne      .LOP_SGET_WIDE_finish                 # success, continue
7586    jmp      common_exceptionThrown             # no, handle exception
7587
7588/* continuation for OP_SGET_OBJECT */
7589
7590    /*
7591     * Go resolve the field
7592     */
7593.LOP_SGET_OBJECT_resolve:
7594    movl     rGLUE,%ecx
7595    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7596    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7597    EXPORT_PC                                   # could throw, need to export
7598    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7599    movl     %eax,OUT_ARG1(%esp)
7600    movl     %ecx,OUT_ARG0(%esp)
7601    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7602    testl    %eax,%eax
7603    jne      .LOP_SGET_OBJECT_finish                 # success, continue
7604    jmp      common_exceptionThrown             # no, handle exception
7605
7606/* continuation for OP_SGET_BOOLEAN */
7607
7608    /*
7609     * Go resolve the field
7610     */
7611.LOP_SGET_BOOLEAN_resolve:
7612    movl     rGLUE,%ecx
7613    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7614    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7615    EXPORT_PC                                   # could throw, need to export
7616    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7617    movl     %eax,OUT_ARG1(%esp)
7618    movl     %ecx,OUT_ARG0(%esp)
7619    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7620    testl    %eax,%eax
7621    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
7622    jmp      common_exceptionThrown             # no, handle exception
7623
7624/* continuation for OP_SGET_BYTE */
7625
7626    /*
7627     * Go resolve the field
7628     */
7629.LOP_SGET_BYTE_resolve:
7630    movl     rGLUE,%ecx
7631    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7632    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7633    EXPORT_PC                                   # could throw, need to export
7634    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7635    movl     %eax,OUT_ARG1(%esp)
7636    movl     %ecx,OUT_ARG0(%esp)
7637    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7638    testl    %eax,%eax
7639    jne      .LOP_SGET_BYTE_finish                 # success, continue
7640    jmp      common_exceptionThrown             # no, handle exception
7641
7642/* continuation for OP_SGET_CHAR */
7643
7644    /*
7645     * Go resolve the field
7646     */
7647.LOP_SGET_CHAR_resolve:
7648    movl     rGLUE,%ecx
7649    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7650    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7651    EXPORT_PC                                   # could throw, need to export
7652    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7653    movl     %eax,OUT_ARG1(%esp)
7654    movl     %ecx,OUT_ARG0(%esp)
7655    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7656    testl    %eax,%eax
7657    jne      .LOP_SGET_CHAR_finish                 # success, continue
7658    jmp      common_exceptionThrown             # no, handle exception
7659
7660/* continuation for OP_SGET_SHORT */
7661
7662    /*
7663     * Go resolve the field
7664     */
7665.LOP_SGET_SHORT_resolve:
7666    movl     rGLUE,%ecx
7667    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7668    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7669    EXPORT_PC                                   # could throw, need to export
7670    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7671    movl     %eax,OUT_ARG1(%esp)
7672    movl     %ecx,OUT_ARG0(%esp)
7673    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7674    testl    %eax,%eax
7675    jne      .LOP_SGET_SHORT_finish                 # success, continue
7676    jmp      common_exceptionThrown             # no, handle exception
7677
7678/* continuation for OP_SPUT */
7679
7680    /*
7681     * Go resolve the field
7682     */
7683.LOP_SPUT_resolve:
7684    movl     rGLUE,%ecx
7685    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7686    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7687    EXPORT_PC                                   # could throw, need to export
7688    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7689    movl     %eax,OUT_ARG1(%esp)
7690    movl     %ecx,OUT_ARG0(%esp)
7691    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7692    testl    %eax,%eax
7693    jne      .LOP_SPUT_finish                 # success, continue
7694    jmp      common_exceptionThrown             # no, handle exception
7695
7696/* continuation for OP_SPUT_WIDE */
7697
7698    /*
7699     * Go resolve the field
7700     */
7701.LOP_SPUT_WIDE_resolve:
7702    movl     rGLUE,%ecx
7703    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7704    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7705    EXPORT_PC                                   # could throw, need to export
7706    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7707    movl     %eax,OUT_ARG1(%esp)
7708    movl     %ecx,OUT_ARG0(%esp)
7709    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7710    testl    %eax,%eax
7711    jne      .LOP_SPUT_WIDE_finish                 # success, continue
7712    jmp      common_exceptionThrown             # no, handle exception
7713
7714/* continuation for OP_SPUT_OBJECT */
7715
7716
7717.LOP_SPUT_OBJECT_continue:
7718    movl      %ecx,offStaticField_value(%eax)    # do the store
7719    testl     %ecx,%ecx                          # stored null object ptr?
7720    FETCH_INST_OPCODE 2 %edx
7721    je        1f                                 # skip card mark if null
7722    movl      rGLUE,%ecx
7723    movl      offField_clazz(%eax),%eax          # eax<- method->clazz
7724    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
7725    shrl      $GC_CARD_SHIFT,%eax               # head to card number
7726    movb      %cl,(%ecx,%eax)                    # mark card
77271:
7728    ADVANCE_PC 2
7729    GOTO_NEXT_R %edx
7730
7731.LOP_SPUT_OBJECT_resolve:
7732    movl     rGLUE,%ecx
7733    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7734    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7735    EXPORT_PC                                   # could throw, need to export
7736    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7737    movl     %eax,OUT_ARG1(%esp)
7738    movl     %ecx,OUT_ARG0(%esp)
7739    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7740    testl    %eax,%eax
7741    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
7742    jmp      common_exceptionThrown             # no, handle exception
7743
7744/* continuation for OP_SPUT_BOOLEAN */
7745
7746    /*
7747     * Go resolve the field
7748     */
7749.LOP_SPUT_BOOLEAN_resolve:
7750    movl     rGLUE,%ecx
7751    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7752    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7753    EXPORT_PC                                   # could throw, need to export
7754    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7755    movl     %eax,OUT_ARG1(%esp)
7756    movl     %ecx,OUT_ARG0(%esp)
7757    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7758    testl    %eax,%eax
7759    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
7760    jmp      common_exceptionThrown             # no, handle exception
7761
7762/* continuation for OP_SPUT_BYTE */
7763
7764    /*
7765     * Go resolve the field
7766     */
7767.LOP_SPUT_BYTE_resolve:
7768    movl     rGLUE,%ecx
7769    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7770    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7771    EXPORT_PC                                   # could throw, need to export
7772    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7773    movl     %eax,OUT_ARG1(%esp)
7774    movl     %ecx,OUT_ARG0(%esp)
7775    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7776    testl    %eax,%eax
7777    jne      .LOP_SPUT_BYTE_finish                 # success, continue
7778    jmp      common_exceptionThrown             # no, handle exception
7779
7780/* continuation for OP_SPUT_CHAR */
7781
7782    /*
7783     * Go resolve the field
7784     */
7785.LOP_SPUT_CHAR_resolve:
7786    movl     rGLUE,%ecx
7787    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7788    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7789    EXPORT_PC                                   # could throw, need to export
7790    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7791    movl     %eax,OUT_ARG1(%esp)
7792    movl     %ecx,OUT_ARG0(%esp)
7793    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7794    testl    %eax,%eax
7795    jne      .LOP_SPUT_CHAR_finish                 # success, continue
7796    jmp      common_exceptionThrown             # no, handle exception
7797
7798/* continuation for OP_SPUT_SHORT */
7799
7800    /*
7801     * Go resolve the field
7802     */
7803.LOP_SPUT_SHORT_resolve:
7804    movl     rGLUE,%ecx
7805    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7806    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7807    EXPORT_PC                                   # could throw, need to export
7808    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7809    movl     %eax,OUT_ARG1(%esp)
7810    movl     %ecx,OUT_ARG0(%esp)
7811    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7812    testl    %eax,%eax
7813    jne      .LOP_SPUT_SHORT_finish                 # success, continue
7814    jmp      common_exceptionThrown             # no, handle exception
7815
7816/* continuation for OP_INVOKE_VIRTUAL */
7817
7818
7819.LOP_INVOKE_VIRTUAL_more:
7820    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7821    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7822    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7823    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7824    testl     %eax,%eax                   # got null?
7825    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
7826    jmp       common_exceptionThrown      # yes, handle exception
7827
7828    /* At this point:
7829     *   eax = resolved base method
7830     *   ecx = scratch
7831     */
7832.LOP_INVOKE_VIRTUAL_continue:
7833    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7834    .if       (!0)
7835    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7836    .endif
7837    GET_VREG_R  %ecx %ecx               # ecx<- "this"
7838    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7839    testl     %ecx,%ecx                 # null this?
7840    je        common_errNullObject      # go if so
7841    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7842    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7843    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7844    jmp       common_invokeMethodNoRange
7845
7846/* continuation for OP_INVOKE_SUPER */
7847
7848    /*
7849     * At this point:
7850     *  ecx = resolved base method [r0]
7851     *  eax = method->clazz [r9]
7852     */
7853.LOP_INVOKE_SUPER_continue:
7854    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7855    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7856    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7857    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
7858    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7859    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7860    jmp     common_invokeMethodNoRange
7861
7862
7863    /* At this point:
7864     * ecx = null (needs to be resolved base method)
7865     * eax = method->clazz
7866    */
7867.LOP_INVOKE_SUPER_resolve:
7868    SPILL_TMP1(%eax)                    # method->clazz
7869    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7870    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7871    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7872    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7873    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7874    testl   %eax,%eax                   # got null?
7875    movl    %eax,%ecx                   # ecx<- resolved base method
7876    UNSPILL_TMP1(%eax)                  # restore method->clazz
7877    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
7878    jmp     common_exceptionThrown      # handle exception
7879
7880    /*
7881     * Throw a NoSuchMethodError with the method name as the message.
7882     *  ecx = resolved base method
7883     */
7884.LOP_INVOKE_SUPER_nsm:
7885    movl    offMethod_name(%ecx),%eax
7886    mov     %eax,OUT_ARG1(%esp)
7887    jmp     common_errNoSuchMethod
7888
7889/* continuation for OP_INVOKE_DIRECT */
7890
7891    /*
7892     * On entry:
7893     *   TMP_SPILL  <- "this" register
7894     * Things a bit ugly on this path, but it's the less
7895     * frequent one.  We'll have to do some reloading.
7896     */
7897.LOP_INVOKE_DIRECT_resolve:
7898     SPILL_TMP1(%ecx)
7899     movl     rGLUE,%ecx
7900     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7901     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7902     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7903     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7904     movl     %eax,OUT_ARG1(%esp)
7905     movl     %ecx,OUT_ARG0(%esp)
7906     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7907     UNSPILL_TMP1(%ecx)
7908     testl    %eax,%eax
7909     jne      .LOP_INVOKE_DIRECT_finish
7910     jmp      common_exceptionThrown
7911
7912/* continuation for OP_INVOKE_STATIC */
7913
7914.LOP_INVOKE_STATIC_continue:
7915    movl      $METHOD_STATIC,%eax
7916    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7917    call      dvmResolveMethod          # call(clazz,ref,flags)
7918    testl     %eax,%eax                 # got null?
7919    jne       common_invokeMethodNoRange
7920    jmp       common_exceptionThrown
7921
7922/* continuation for OP_INVOKE_INTERFACE */
7923
7924.LOP_INVOKE_INTERFACE_continue:
7925    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7926    testl      %eax,%eax
7927    je         common_exceptionThrown
7928    jmp        common_invokeMethodNoRange
7929
7930/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7931
7932
7933.LOP_INVOKE_VIRTUAL_RANGE_more:
7934    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7935    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7936    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7937    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7938    testl     %eax,%eax                   # got null?
7939    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
7940    jmp       common_exceptionThrown      # yes, handle exception
7941
7942    /* At this point:
7943     *   eax = resolved base method
7944     *   ecx = scratch
7945     */
7946.LOP_INVOKE_VIRTUAL_RANGE_continue:
7947    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7948    .if       (!1)
7949    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7950    .endif
7951    GET_VREG_R  %ecx %ecx               # ecx<- "this"
7952    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7953    testl     %ecx,%ecx                 # null this?
7954    je        common_errNullObject      # go if so
7955    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7956    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7957    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7958    jmp       common_invokeMethodRange
7959
7960/* continuation for OP_INVOKE_SUPER_RANGE */
7961
7962    /*
7963     * At this point:
7964     *  ecx = resolved base method [r0]
7965     *  eax = method->clazz [r9]
7966     */
7967.LOP_INVOKE_SUPER_RANGE_continue:
7968    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7969    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7970    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7971    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
7972    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7973    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7974    jmp     common_invokeMethodRange
7975
7976
7977    /* At this point:
7978     * ecx = null (needs to be resolved base method)
7979     * eax = method->clazz
7980    */
7981.LOP_INVOKE_SUPER_RANGE_resolve:
7982    SPILL_TMP1(%eax)                    # method->clazz
7983    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7984    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7985    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7986    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7987    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7988    testl   %eax,%eax                   # got null?
7989    movl    %eax,%ecx                   # ecx<- resolved base method
7990    UNSPILL_TMP1(%eax)                  # restore method->clazz
7991    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
7992    jmp     common_exceptionThrown      # handle exception
7993
7994    /*
7995     * Throw a NoSuchMethodError with the method name as the message.
7996     *  ecx = resolved base method
7997     */
7998.LOP_INVOKE_SUPER_RANGE_nsm:
7999    movl    offMethod_name(%ecx),%eax
8000    mov     %eax,OUT_ARG1(%esp)
8001    jmp     common_errNoSuchMethod
8002
8003/* continuation for OP_INVOKE_DIRECT_RANGE */
8004
8005    /*
8006     * On entry:
8007     *   TMP_SPILL  <- "this" register
8008     * Things a bit ugly on this path, but it's the less
8009     * frequent one.  We'll have to do some reloading.
8010     */
8011.LOP_INVOKE_DIRECT_RANGE_resolve:
8012     SPILL_TMP1(%ecx)
8013     movl     rGLUE,%ecx
8014     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
8015     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
8016     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8017     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
8018     movl     %eax,OUT_ARG1(%esp)
8019     movl     %ecx,OUT_ARG0(%esp)
8020     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
8021     UNSPILL_TMP1(%ecx)
8022     testl    %eax,%eax
8023     jne      .LOP_INVOKE_DIRECT_RANGE_finish
8024     jmp      common_exceptionThrown
8025
8026/* continuation for OP_INVOKE_STATIC_RANGE */
8027
8028.LOP_INVOKE_STATIC_RANGE_continue:
8029    movl      $METHOD_STATIC,%eax
8030    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
8031    call      dvmResolveMethod          # call(clazz,ref,flags)
8032    testl     %eax,%eax                 # got null?
8033    jne       common_invokeMethodRange
8034    jmp       common_exceptionThrown
8035
8036/* continuation for OP_INVOKE_INTERFACE_RANGE */
8037
8038.LOP_INVOKE_INTERFACE_RANGE_continue:
8039    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
8040    testl      %eax,%eax
8041    je         common_exceptionThrown
8042    jmp        common_invokeMethodRange
8043
8044/* continuation for OP_FLOAT_TO_INT */
8045
8046
8047.LOP_FLOAT_TO_INT_continue:
8048    .if 0
8049    movl     $0x80000000,%eax
8050    xorl     4(rFP,%ecx,4),%eax
8051    orl      (rFP,%ecx,4),%eax
8052    .else
8053    cmpl     $0x80000000,(rFP,%ecx,4)
8054    .endif
8055    je       .LOP_FLOAT_TO_INT_special_case # fix up result
8056
8057.LOP_FLOAT_TO_INT_finish:
8058    ADVANCE_PC 1
8059    GOTO_NEXT_R %edx
8060
8061.LOP_FLOAT_TO_INT_special_case:
8062    fnstsw   %ax
8063    sahf
8064    jp       .LOP_FLOAT_TO_INT_isNaN
8065    adcl     $-1,(rFP,%ecx,4)
8066    .if 0
8067    adcl     $-1,4(rFP,%ecx,4)
8068    .endif
8069   jmp       .LOP_FLOAT_TO_INT_finish
8070.LOP_FLOAT_TO_INT_isNaN:
8071    movl      $0,(rFP,%ecx,4)
8072    .if 0
8073    movl      $0,4(rFP,%ecx,4)
8074    .endif
8075    jmp       .LOP_FLOAT_TO_INT_finish
8076
8077/* continuation for OP_FLOAT_TO_LONG */
8078
8079
8080.LOP_FLOAT_TO_LONG_continue:
8081    .if 1
8082    movl     $0x80000000,%eax
8083    xorl     4(rFP,%ecx,4),%eax
8084    orl      (rFP,%ecx,4),%eax
8085    .else
8086    cmpl     $0x80000000,(rFP,%ecx,4)
8087    .endif
8088    je       .LOP_FLOAT_TO_LONG_special_case # fix up result
8089
8090.LOP_FLOAT_TO_LONG_finish:
8091    ADVANCE_PC 1
8092    GOTO_NEXT_R %edx
8093
8094.LOP_FLOAT_TO_LONG_special_case:
8095    fnstsw   %ax
8096    sahf
8097    jp       .LOP_FLOAT_TO_LONG_isNaN
8098    adcl     $-1,(rFP,%ecx,4)
8099    .if 1
8100    adcl     $-1,4(rFP,%ecx,4)
8101    .endif
8102   jmp       .LOP_FLOAT_TO_LONG_finish
8103.LOP_FLOAT_TO_LONG_isNaN:
8104    movl      $0,(rFP,%ecx,4)
8105    .if 1
8106    movl      $0,4(rFP,%ecx,4)
8107    .endif
8108    jmp       .LOP_FLOAT_TO_LONG_finish
8109
8110/* continuation for OP_DOUBLE_TO_INT */
8111
8112
8113.LOP_DOUBLE_TO_INT_continue:
8114    .if 0
8115    movl     $0x80000000,%eax
8116    xorl     4(rFP,%ecx,4),%eax
8117    orl      (rFP,%ecx,4),%eax
8118    .else
8119    cmpl     $0x80000000,(rFP,%ecx,4)
8120    .endif
8121    je       .LOP_DOUBLE_TO_INT_special_case # fix up result
8122
8123.LOP_DOUBLE_TO_INT_finish:
8124    ADVANCE_PC 1
8125    GOTO_NEXT_R %edx
8126
8127.LOP_DOUBLE_TO_INT_special_case:
8128    fnstsw   %ax
8129    sahf
8130    jp       .LOP_DOUBLE_TO_INT_isNaN
8131    adcl     $-1,(rFP,%ecx,4)
8132    .if 0
8133    adcl     $-1,4(rFP,%ecx,4)
8134    .endif
8135   jmp       .LOP_DOUBLE_TO_INT_finish
8136.LOP_DOUBLE_TO_INT_isNaN:
8137    movl      $0,(rFP,%ecx,4)
8138    .if 0
8139    movl      $0,4(rFP,%ecx,4)
8140    .endif
8141    jmp       .LOP_DOUBLE_TO_INT_finish
8142
8143/* continuation for OP_DOUBLE_TO_LONG */
8144
8145
8146.LOP_DOUBLE_TO_LONG_continue:
8147    .if 1
8148    movl     $0x80000000,%eax
8149    xorl     4(rFP,%ecx,4),%eax
8150    orl      (rFP,%ecx,4),%eax
8151    .else
8152    cmpl     $0x80000000,(rFP,%ecx,4)
8153    .endif
8154    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result
8155
8156.LOP_DOUBLE_TO_LONG_finish:
8157    ADVANCE_PC 1
8158    GOTO_NEXT_R %edx
8159
8160.LOP_DOUBLE_TO_LONG_special_case:
8161    fnstsw   %ax
8162    sahf
8163    jp       .LOP_DOUBLE_TO_LONG_isNaN
8164    adcl     $-1,(rFP,%ecx,4)
8165    .if 1
8166    adcl     $-1,4(rFP,%ecx,4)
8167    .endif
8168   jmp       .LOP_DOUBLE_TO_LONG_finish
8169.LOP_DOUBLE_TO_LONG_isNaN:
8170    movl      $0,(rFP,%ecx,4)
8171    .if 1
8172    movl      $0,4(rFP,%ecx,4)
8173    .endif
8174    jmp       .LOP_DOUBLE_TO_LONG_finish
8175
8176/* continuation for OP_DIV_INT */
8177.LOP_DIV_INT_continue_div:
8178    cltd
8179    idivl   %ecx
8180.LOP_DIV_INT_finish_div:
8181    SET_VREG %eax rINST
8182    FETCH_INST_OPCODE 2 %edx
8183    ADVANCE_PC 2
8184    GOTO_NEXT_R %edx
8185
8186/* continuation for OP_REM_INT */
8187.LOP_REM_INT_continue_div:
8188    cltd
8189    idivl   %ecx
8190.LOP_REM_INT_finish_div:
8191    SET_VREG %edx rINST
8192    FETCH_INST_OPCODE 2 %edx
8193    ADVANCE_PC 2
8194    GOTO_NEXT_R %edx
8195
8196/* continuation for OP_MUL_LONG */
8197
8198.LOP_MUL_LONG_continue:
8199    leal      (%ecx,%edx),%edx     # full result now in %edx:%eax
8200    UNSPILL_TMP2(%esi)             # Restore Dalvik PC
8201    FETCH_INST_OPCODE 2 %ecx       # Fetch next instruction
8202    movl      %edx,4(rFP,rINST,4)  # v[B+1]<- %edx
8203    movl      %eax,(rFP,rINST,4)   # v[B]<- %eax
8204    ADVANCE_PC 2
8205    GOTO_NEXT_R %ecx
8206
8207/* continuation for OP_DIV_LONG */
8208
8209.LOP_DIV_LONG_continue:
8210    call     __divdi3
8211.LOP_DIV_LONG_finish:
8212    SET_VREG_WORD %edx rINST 1
8213    SET_VREG_WORD %eax rINST 0
8214    FETCH_INST_OPCODE 2 %edx
8215    ADVANCE_PC 2
8216    GOTO_NEXT_R %edx
8217
8218.LOP_DIV_LONG_check_zero:
8219    testl   %edx,%edx
8220    jne     .LOP_DIV_LONG_notSpecial
8221    jmp     common_errDivideByZero
8222.LOP_DIV_LONG_check_neg1:
8223    testl   %edx,%eax
8224    jne     .LOP_DIV_LONG_notSpecial
8225    GET_VREG_WORD %edx %ecx 0
8226    GET_VREG_WORD %ecx %ecx 1
8227    testl    %edx,%edx
8228    jne      .LOP_DIV_LONG_notSpecial1
8229    cmpl     $0x80000000,%ecx
8230    jne      .LOP_DIV_LONG_notSpecial1
8231    /* minint / -1, return minint on div, 0 on rem */
8232    xorl     %eax,%eax
8233    movl     $0x80000000,%edx
8234    jmp      .LOP_DIV_LONG_finish
8235
8236/* continuation for OP_REM_LONG */
8237
8238.LOP_REM_LONG_continue:
8239    call     __moddi3
8240.LOP_REM_LONG_finish:
8241    SET_VREG_WORD %edx rINST 1
8242    SET_VREG_WORD %eax rINST 0
8243    FETCH_INST_OPCODE 2 %edx
8244    ADVANCE_PC 2
8245    GOTO_NEXT_R %edx
8246
8247.LOP_REM_LONG_check_zero:
8248    testl   %edx,%edx
8249    jne     .LOP_REM_LONG_notSpecial
8250    jmp     common_errDivideByZero
8251.LOP_REM_LONG_check_neg1:
8252    testl   %edx,%eax
8253    jne     .LOP_REM_LONG_notSpecial
8254    GET_VREG_WORD %edx %ecx 0
8255    GET_VREG_WORD %ecx %ecx 1
8256    testl    %edx,%edx
8257    jne      .LOP_REM_LONG_notSpecial1
8258    cmpl     $0x80000000,%ecx
8259    jne      .LOP_REM_LONG_notSpecial1
8260    /* minint / -1, return minint on div, 0 on rem */
8261    xorl     %eax,%eax
8262    movl     $0,%edx
8263    jmp      .LOP_REM_LONG_finish
8264
8265/* continuation for OP_SHL_LONG */
8266
8267.LOP_SHL_LONG_finish:
8268    SET_VREG_WORD %eax rINST 0          # v[AA+0]<- %eax
8269    ADVANCE_PC 2
8270    GOTO_NEXT_R %edx
8271
8272/* continuation for OP_SHR_LONG */
8273
8274
8275.LOP_SHR_LONG_finish:
8276    SET_VREG_WORD %eax rINST 0          # v[AA+0]<- eax
8277    ADVANCE_PC 2
8278    GOTO_NEXT_R %edx
8279
8280/* continuation for OP_USHR_LONG */
8281
8282
8283.LOP_USHR_LONG_finish:
8284    SET_VREG_WORD %eax rINST 0         # v[BB+0]<- eax
8285    ADVANCE_PC 2
8286    GOTO_NEXT_R %edx
8287
8288/* continuation for OP_DIV_INT_2ADDR */
8289.LOP_DIV_INT_2ADDR_continue_div2addr:
8290    cltd
8291    idivl   %ecx
8292.LOP_DIV_INT_2ADDR_finish_div2addr:
8293    SET_VREG %eax rINST
8294    FETCH_INST_OPCODE 1 %edx
8295    ADVANCE_PC 1
8296    GOTO_NEXT_R %edx
8297
8298/* continuation for OP_REM_INT_2ADDR */
8299.LOP_REM_INT_2ADDR_continue_div2addr:
8300    cltd
8301    idivl   %ecx
8302.LOP_REM_INT_2ADDR_finish_div2addr:
8303    SET_VREG %edx rINST
8304    FETCH_INST_OPCODE 1 %edx
8305    ADVANCE_PC 1
8306    GOTO_NEXT_R %edx
8307
8308/* continuation for OP_MUL_LONG_2ADDR */
8309
8310.LOP_MUL_LONG_2ADDR_continue:
8311    leal      (%ecx,%edx),%edx         # full result now in %edx:%eax
8312    movl      %edx,4(%esi)             # v[A+1]<- %edx
8313    movl      %eax,(%esi)              # v[A]<- %eax
8314    UNSPILL_TMP2(%esi)
8315    FETCH_INST_OPCODE 1 %ecx
8316    UNSPILL(rFP)
8317    ADVANCE_PC 1
8318    GOTO_NEXT_R %ecx
8319
8320/* continuation for OP_DIV_LONG_2ADDR */
8321
8322.LOP_DIV_LONG_2ADDR_continue:
8323    movl     %eax,OUT_ARG3(%esp)
8324    movl     %edx,OUT_ARG0(%esp)
8325    movl     %ecx,OUT_ARG1(%esp)
8326    call     __divdi3
8327.LOP_DIV_LONG_2ADDR_finish:
8328    SET_VREG_WORD %edx rINST 1
8329    SET_VREG_WORD %eax rINST 0
8330    FETCH_INST_OPCODE 1 %edx
8331    ADVANCE_PC 1
8332    GOTO_NEXT_R %edx
8333
8334.LOP_DIV_LONG_2ADDR_check_zero:
8335    testl   %edx,%edx
8336    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8337    jmp     common_errDivideByZero
8338.LOP_DIV_LONG_2ADDR_check_neg1:
8339    testl   %edx,%eax
8340    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8341    GET_VREG_WORD %edx rINST 0
8342    GET_VREG_WORD %ecx rINST 1
8343    testl    %edx,%edx
8344    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8345    cmpl     $0x80000000,%ecx
8346    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8347    /* minint / -1, return minint on div, 0 on rem */
8348    xorl     %eax,%eax
8349    movl     $0x80000000,%edx
8350    jmp      .LOP_DIV_LONG_2ADDR_finish
8351
8352/* continuation for OP_REM_LONG_2ADDR */
8353
8354.LOP_REM_LONG_2ADDR_continue:
8355    movl     %eax,OUT_ARG3(%esp)
8356    movl     %edx,OUT_ARG0(%esp)
8357    movl     %ecx,OUT_ARG1(%esp)
8358    call     __moddi3
8359.LOP_REM_LONG_2ADDR_finish:
8360    SET_VREG_WORD %edx rINST 1
8361    SET_VREG_WORD %eax rINST 0
8362    FETCH_INST_OPCODE 1 %edx
8363    ADVANCE_PC 1
8364    GOTO_NEXT_R %edx
8365
8366.LOP_REM_LONG_2ADDR_check_zero:
8367    testl   %edx,%edx
8368    jne     .LOP_REM_LONG_2ADDR_notSpecial
8369    jmp     common_errDivideByZero
8370.LOP_REM_LONG_2ADDR_check_neg1:
8371    testl   %edx,%eax
8372    jne     .LOP_REM_LONG_2ADDR_notSpecial
8373    GET_VREG_WORD %edx rINST 0
8374    GET_VREG_WORD %ecx rINST 1
8375    testl    %edx,%edx
8376    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8377    cmpl     $0x80000000,%ecx
8378    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8379    /* minint / -1, return minint on div, 0 on rem */
8380    xorl     %eax,%eax
8381    movl     $0,%edx
8382    jmp      .LOP_REM_LONG_2ADDR_finish
8383
8384/* continuation for OP_SHL_LONG_2ADDR */
8385
8386
8387.LOP_SHL_LONG_2ADDR_finish:
8388    FETCH_INST_OPCODE 1 %edx
8389    SET_VREG_WORD %eax rINST 0         # v[AA+0]<- eax
8390    ADVANCE_PC 1
8391    GOTO_NEXT_R %edx
8392
8393/* continuation for OP_SHR_LONG_2ADDR */
8394
8395
8396.LOP_SHR_LONG_2ADDR_finish:
8397    FETCH_INST_OPCODE 1 %edx
8398    SET_VREG_WORD %eax rINST 0    # v[AA+0]<- eax
8399    ADVANCE_PC 1
8400    GOTO_NEXT_R %edx
8401
8402/* continuation for OP_USHR_LONG_2ADDR */
8403
8404
8405.LOP_USHR_LONG_2ADDR_finish:
8406    FETCH_INST_OPCODE 1 %edx
8407    SET_VREG_WORD %eax rINST 0         # v[AA+0]<- eax
8408    ADVANCE_PC 1
8409    GOTO_NEXT_R %edx
8410
8411/* continuation for OP_DIV_INT_LIT16 */
8412.LOP_DIV_INT_LIT16_continue_div:
8413    cltd
8414    idivl   %ecx
8415.LOP_DIV_INT_LIT16_finish_div:
8416    SET_VREG %eax rINST
8417    FETCH_INST_OPCODE 2 %edx
8418    ADVANCE_PC 2
8419    GOTO_NEXT_R %edx
8420
8421/* continuation for OP_REM_INT_LIT16 */
8422.LOP_REM_INT_LIT16_continue_div:
8423    cltd
8424    idivl   %ecx
8425.LOP_REM_INT_LIT16_finish_div:
8426    SET_VREG %edx rINST
8427    FETCH_INST_OPCODE 2 %edx
8428    ADVANCE_PC 2
8429    GOTO_NEXT_R %edx
8430
8431/* continuation for OP_DIV_INT_LIT8 */
8432.LOP_DIV_INT_LIT8_continue_div:
8433    cltd
8434    idivl   %ecx
8435.LOP_DIV_INT_LIT8_finish_div:
8436    SET_VREG %eax rINST
8437    FETCH_INST_OPCODE 2 %edx
8438    ADVANCE_PC 2
8439    GOTO_NEXT_R %edx
8440
8441/* continuation for OP_REM_INT_LIT8 */
8442.LOP_REM_INT_LIT8_continue_div:
8443    cltd
8444    idivl   %ecx
8445.LOP_REM_INT_LIT8_finish_div:
8446    SET_VREG %edx rINST
8447    FETCH_INST_OPCODE 2 %edx
8448    ADVANCE_PC 2
8449    GOTO_NEXT_R %edx
8450
8451/* continuation for OP_IGET_VOLATILE */
8452
8453
8454.LOP_IGET_VOLATILE_resolve:
8455    EXPORT_PC
8456    movl    offGlue_method(%edx),%edx           # edx<- current method
8457    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8458    SPILL_TMP1(%ecx)                            # save obj pointer across call
8459    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
8460    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8461    UNSPILL_TMP1(%ecx)
8462    testl   %eax,%eax                           #  returns InstrField ptr
8463    jne     .LOP_IGET_VOLATILE_finish
8464    jmp     common_exceptionThrown
8465
8466.LOP_IGET_VOLATILE_finish:
8467    /*
8468     * Currently:
8469     *   eax holds resolved field
8470     *   ecx holds object
8471     *   rINST holds A
8472     */
8473    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
8474    testl   %ecx,%ecx                           # object null?
8475    je      common_errNullObject                # object was null
8476    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
8477    movl    rINST,%eax                          # eax<- A
8478    FETCH_INST_OPCODE 2 %edx
8479    SET_VREG %ecx %eax
8480    ADVANCE_PC 2
8481    GOTO_NEXT_R %edx
8482
8483/* continuation for OP_IPUT_VOLATILE */
8484
8485
8486.LOP_IPUT_VOLATILE_resolve:
8487    EXPORT_PC
8488    movl    offGlue_method(%edx),%edx           # edx<- current method
8489    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8490    SPILL_TMP1(%ecx)                            # save obj pointer across call
8491    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
8492    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8493    UNSPILL_TMP1(%ecx)
8494    testl   %eax,%eax                           # returns InstrField ptr
8495    jne     .LOP_IPUT_VOLATILE_finish
8496    jmp     common_exceptionThrown
8497
8498.LOP_IPUT_VOLATILE_finish:
8499    /*
8500     * Currently:
8501     *   eax holds resolved field
8502     *   ecx holds object
8503     *   rINST holds A
8504     */
8505    GET_VREG_R rINST rINST                       # rINST<- v[A]
8506    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8507    testl   %ecx,%ecx                            # object null?
8508    je      common_errNullObject                 # object was null
8509    FETCH_INST_OPCODE 2 %edx
8510    movl   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
8511    ADVANCE_PC 2
8512    GOTO_NEXT_R %edx
8513
8514/* continuation for OP_SGET_VOLATILE */
8515
8516    /*
8517     * Go resolve the field
8518     */
8519.LOP_SGET_VOLATILE_resolve:
8520    movl     rGLUE,%ecx
8521    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8522    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8523    EXPORT_PC                                   # could throw, need to export
8524    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8525    movl     %eax,OUT_ARG1(%esp)
8526    movl     %ecx,OUT_ARG0(%esp)
8527    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8528    testl    %eax,%eax
8529    jne      .LOP_SGET_VOLATILE_finish                 # success, continue
8530    jmp      common_exceptionThrown             # no, handle exception
8531
8532/* continuation for OP_SPUT_VOLATILE */
8533
8534    /*
8535     * Go resolve the field
8536     */
8537.LOP_SPUT_VOLATILE_resolve:
8538    movl     rGLUE,%ecx
8539    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8540    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8541    EXPORT_PC                                   # could throw, need to export
8542    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8543    movl     %eax,OUT_ARG1(%esp)
8544    movl     %ecx,OUT_ARG0(%esp)
8545    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8546    testl    %eax,%eax
8547    jne      .LOP_SPUT_VOLATILE_finish                 # success, continue
8548    jmp      common_exceptionThrown             # no, handle exception
8549
8550/* continuation for OP_IGET_OBJECT_VOLATILE */
8551
8552
8553.LOP_IGET_OBJECT_VOLATILE_resolve:
8554    EXPORT_PC
8555    movl    offGlue_method(%edx),%edx           # edx<- current method
8556    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8557    SPILL_TMP1(%ecx)                            # save obj pointer across call
8558    movl    %edx,OUT_ARG0(%esp)                  # pass in method->clazz
8559    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8560    UNSPILL_TMP1(%ecx)
8561    testl   %eax,%eax                           #  returns InstrField ptr
8562    jne     .LOP_IGET_OBJECT_VOLATILE_finish
8563    jmp     common_exceptionThrown
8564
8565.LOP_IGET_OBJECT_VOLATILE_finish:
8566    /*
8567     * Currently:
8568     *   eax holds resolved field
8569     *   ecx holds object
8570     *   rINST holds A
8571     */
8572    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
8573    testl   %ecx,%ecx                           # object null?
8574    je      common_errNullObject                # object was null
8575    movl   (%ecx,%eax,1),%ecx                  # ecx<- obj.field (8/16/32 bits)
8576    movl    rINST,%eax                          # eax<- A
8577    FETCH_INST_OPCODE 2 %edx
8578    SET_VREG %ecx %eax
8579    ADVANCE_PC 2
8580    GOTO_NEXT_R %edx
8581
8582/* continuation for OP_EXECUTE_INLINE */
8583
8584.LOP_EXECUTE_INLINE_continue:
8585    /*
8586     * Extract args, call function.
8587     *  ecx = #of args (0-4)
8588     *  eax = call index
8589     *  @esp = return addr
8590     *  esp is -4 from normal
8591     *
8592     *  Go ahead and load all 4 args, even if not used.
8593     */
8594    movzwl    4(rPC),%edx
8595
8596    movl      $0xf,%ecx
8597    andl      %edx,%ecx
8598    GET_VREG_R  %ecx %ecx
8599    sarl      $4,%edx
8600    movl      %ecx,4+OUT_ARG0(%esp)
8601
8602    movl      $0xf,%ecx
8603    andl      %edx,%ecx
8604    GET_VREG_R  %ecx %ecx
8605    sarl      $4,%edx
8606    movl      %ecx,4+OUT_ARG1(%esp)
8607
8608    movl      $0xf,%ecx
8609    andl      %edx,%ecx
8610    GET_VREG_R  %ecx %ecx
8611    sarl      $4,%edx
8612    movl      %ecx,4+OUT_ARG2(%esp)
8613
8614    movl      $0xf,%ecx
8615    andl      %edx,%ecx
8616    GET_VREG_R  %ecx %ecx
8617    sarl      $4,%edx
8618    movl      %ecx,4+OUT_ARG3(%esp)
8619
8620    sall      $4,%eax      # index *= sizeof(table entry)
8621    jmp       *gDvmInlineOpsTable(%eax)
8622    # will return to caller of .LOP_EXECUTE_INLINE_continue
8623
8624/* continuation for OP_IPUT_OBJECT_QUICK */
8625
8626.LOP_IPUT_OBJECT_QUICK_finish:
8627    testl     rINST,rINST               # did we store null?
8628    FETCH_INST_OPCODE 2 %edx
8629    movl      offGlue_cardTable(%eax),%eax  # get card table base
8630    je        1f                            # skip card mark if null store
8631    shrl      $GC_CARD_SHIFT,%ecx          # object head to card number
8632    movb      %al,(%eax,%ecx)               # mark card based on object head
86331:
8634    ADVANCE_PC 2
8635    GOTO_NEXT_R %edx
8636
8637/* continuation for OP_IPUT_OBJECT_VOLATILE */
8638
8639
8640.LOP_IPUT_OBJECT_VOLATILE_resolve:
8641    EXPORT_PC
8642    movl    offGlue_method(%edx),%edx           # edx<- current method
8643    movl    offMethod_clazz(%edx),%edx          # edx<- method->clazz
8644    SPILL_TMP1(%ecx)                            # save obj pointer across call
8645    movl    %edx,OUT_ARG0(%esp)                 # pass in method->clazz
8646    call    dvmResolveInstField                 #  ... to dvmResolveInstField
8647    UNSPILL_TMP1(%ecx)
8648    testl   %eax,%eax                           # returns InstrField ptr
8649    jne     .LOP_IPUT_OBJECT_VOLATILE_finish
8650    jmp     common_exceptionThrown
8651
8652.LOP_IPUT_OBJECT_VOLATILE_finish:
8653    /*
8654     * Currently:
8655     *   eax holds resolved field
8656     *   ecx holds object
8657     *   %edx is scratch, but needs to be unspilled
8658     *   rINST holds A
8659     */
8660    GET_VREG_R rINST rINST                      # rINST<- v[A]
8661    movl    offInstField_byteOffset(%eax),%eax  # eax<- byte offset of field
8662    testl   %ecx,%ecx                           # object null?
8663    je      common_errNullObject                # object was null
8664    movl    rINST,(%ecx,%eax)      # obj.field <- v[A](8/16/32 bits)
8665    movl    rGLUE,%eax
8666    testl   rINST,rINST                         # stored a NULL?
8667    movl    offGlue_cardTable(%eax),%eax        # get card table base
8668    FETCH_INST_OPCODE 2 %edx
8669    je      1f                                  # skip card mark if null store
8670    shrl    $GC_CARD_SHIFT,%ecx                # object head to card number
8671    movb    %al,(%eax,%ecx)                     # mark card using object head
86721:
8673    ADVANCE_PC 2
8674    GOTO_NEXT_R %edx
8675
8676/* continuation for OP_SGET_OBJECT_VOLATILE */
8677
8678    /*
8679     * Go resolve the field
8680     */
8681.LOP_SGET_OBJECT_VOLATILE_resolve:
8682    movl     rGLUE,%ecx
8683    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8684    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8685    EXPORT_PC                                   # could throw, need to export
8686    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8687    movl     %eax,OUT_ARG1(%esp)
8688    movl     %ecx,OUT_ARG0(%esp)
8689    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8690    testl    %eax,%eax
8691    jne      .LOP_SGET_OBJECT_VOLATILE_finish                 # success, continue
8692    jmp      common_exceptionThrown             # no, handle exception
8693
8694/* continuation for OP_SPUT_OBJECT_VOLATILE */
8695
8696
8697.LOP_SPUT_OBJECT_VOLATILE_continue:
8698    movl      %ecx,offStaticField_value(%eax)    # do the store
8699    testl     %ecx,%ecx                          # stored null object ptr?
8700    FETCH_INST_OPCODE 2 %edx
8701    je        1f                                 # skip card mark if null
8702    movl      rGLUE,%ecx
8703    movl      offField_clazz(%eax),%eax          # eax<- method->clazz
8704    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
8705    shrl      $GC_CARD_SHIFT,%eax               # head to card number
8706    movb      %cl,(%ecx,%eax)                    # mark card
87071:
8708    ADVANCE_PC 2
8709    GOTO_NEXT_R %edx
8710
8711.LOP_SPUT_OBJECT_VOLATILE_resolve:
8712    movl     rGLUE,%ecx
8713    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8714    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8715    EXPORT_PC                                   # could throw, need to export
8716    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8717    movl     %eax,OUT_ARG1(%esp)
8718    movl     %ecx,OUT_ARG0(%esp)
8719    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8720    testl    %eax,%eax
8721    jne      .LOP_SPUT_OBJECT_VOLATILE_finish                 # success, continue
8722    jmp      common_exceptionThrown             # no, handle exception
8723
8724    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8725    .global dvmAsmSisterEnd
8726dvmAsmSisterEnd:
8727
8728/* File: x86/entry.S */
8729/*
8730 * Copyright (C) 2008 The Android Open Source Project
8731 *
8732 * Licensed under the Apache License, Version 2.0 (the "License");
8733 * you may not use this file except in compliance with the License.
8734 * You may obtain a copy of the License at
8735 *
8736 *      http://www.apache.org/licenses/LICENSE-2.0
8737 *
8738 * Unless required by applicable law or agreed to in writing, software
8739 * distributed under the License is distributed on an "AS IS" BASIS,
8740 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8741 * See the License for the specific language governing permissions and
8742 * limitations under the License.
8743 */
8744
8745
8746    .text
8747    .global dvmMterpStdRun
8748    .type   dvmMterpStdRun, %function
8749/*
8750 * bool dvmMterpStdRun(MterpGlue* glue)
8751 *
8752 * Interpreter entry point.  Returns changeInterp.
8753 *
8754 */
8755dvmMterpStdRun:
8756    movl    4(%esp), %ecx        # get incoming rGLUE
8757    push    %ebp                 # save caller base pointer
8758    push    %ecx                 # save rGLUE at (%ebp)
8759    movl    %esp, %ebp           # set our %ebp
8760/*
8761 * At this point we've allocated two slots on the stack
8762 * via push and stack is 8-byte aligned.  Allocate space
8763 * for 8 spill slots, 3 local slots, 5 arg slots + 2 slots for
8764 * padding to bring us to 16-byte alignment
8765 */
8766    subl    $(FRAME_SIZE-8), %esp
8767
8768/* Spill callee save regs */
8769    movl    %edi,EDI_SPILL(%ebp)
8770    movl    %esi,ESI_SPILL(%ebp)
8771    movl    %ebx,EBX_SPILL(%ebp)
8772
8773/* Set up "named" registers */
8774    movl    offGlue_pc(%ecx),rPC
8775    movl    offGlue_fp(%ecx),rFP
8776
8777/* Remember %esp for future "longjmp" */
8778    movl    %esp,offGlue_bailPtr(%ecx)
8779
8780/* How to start? */
8781    movb    offGlue_entryPoint(%ecx),%al
8782
8783/* Normal start? */
8784    cmpb    $kInterpEntryInstr,%al
8785    jne     .Lnot_instr
8786
8787   /* Normal case: start executing the instruction at rPC */
8788    FETCH_INST
8789    GOTO_NEXT
8790
8791.Lnot_instr:
8792    /* Reset to normal case */
8793    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8794    cmpb   $kInterpEntryReturn,%al
8795    je     common_returnFromMethod
8796    cmpb   $kInterpEntryThrow,%al
8797    je     common_exceptionThrown
8798    movzx  %al,%eax
8799    movl   %eax,OUT_ARG1(%esp)
8800    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
8801    call   printf
8802    call   dvmAbort
8803    /* Not reached */
8804
8805
8806    .global dvmMterpStdBail
8807    .type   dvmMterpStdBail, %function
8808/*
8809 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8810 *
8811 * Restore the stack pointer and PC from the save point established on entry.
8812 * This is essentially the same as a longjmp, but should be cheaper.  The
8813 * last instruction causes us to return to whoever called dvmMterpStdRun.
8814 *
8815 * We're not going to build a standard frame here, so the arg accesses will
8816 * look a little strange.
8817 *
8818 * On entry:
8819 *  esp+4 (arg0)  MterpGlue* glue
8820 *  esp+8 (arg1)  bool changeInterp
8821 */
8822dvmMterpStdBail:
8823    movl    4(%esp),%ecx                 # grab glue
8824    movl    8(%esp),%eax                 # changeInterp to return reg
8825    movl    offGlue_bailPtr(%ecx),%esp   # Restore "setjmp" esp
8826    movl    %esp,%ebp
8827    addl    $(FRAME_SIZE-8), %ebp       # Restore %ebp at point of setjmp
8828    movl    EDI_SPILL(%ebp),%edi
8829    movl    ESI_SPILL(%ebp),%esi
8830    movl    EBX_SPILL(%ebp),%ebx
8831    movl    PREV_FP(%ebp),%ebp           # restore caller's ebp
8832    addl    $FRAME_SIZE,%esp                    # strip frame
8833    ret                                  # return to dvmMterpStdRun's caller
8834
8835
8836/*
8837 * Strings
8838 */
8839    .section    .rodata
8840.LstrBadEntryPoint:
8841    .asciz  "Bad entry point %d\n"
8842
8843
8844/*
8845 * FIXME: Should have the config/rebuild mechanism generate this
8846 * for targets that need it.
8847 */
8848
8849/* Jump table */
8850dvmAsmInstructionJmpTable = .LdvmAsmInstructionJmpTable
8851.LdvmAsmInstructionJmpTable:
8852.long .L_OP_NOP
8853.long .L_OP_MOVE
8854.long .L_OP_MOVE_FROM16
8855.long .L_OP_MOVE_16
8856.long .L_OP_MOVE_WIDE
8857.long .L_OP_MOVE_WIDE_FROM16
8858.long .L_OP_MOVE_WIDE_16
8859.long .L_OP_MOVE_OBJECT
8860.long .L_OP_MOVE_OBJECT_FROM16
8861.long .L_OP_MOVE_OBJECT_16
8862.long .L_OP_MOVE_RESULT
8863.long .L_OP_MOVE_RESULT_WIDE
8864.long .L_OP_MOVE_RESULT_OBJECT
8865.long .L_OP_MOVE_EXCEPTION
8866.long .L_OP_RETURN_VOID
8867.long .L_OP_RETURN
8868.long .L_OP_RETURN_WIDE
8869.long .L_OP_RETURN_OBJECT
8870.long .L_OP_CONST_4
8871.long .L_OP_CONST_16
8872.long .L_OP_CONST
8873.long .L_OP_CONST_HIGH16
8874.long .L_OP_CONST_WIDE_16
8875.long .L_OP_CONST_WIDE_32
8876.long .L_OP_CONST_WIDE
8877.long .L_OP_CONST_WIDE_HIGH16
8878.long .L_OP_CONST_STRING
8879.long .L_OP_CONST_STRING_JUMBO
8880.long .L_OP_CONST_CLASS
8881.long .L_OP_MONITOR_ENTER
8882.long .L_OP_MONITOR_EXIT
8883.long .L_OP_CHECK_CAST
8884.long .L_OP_INSTANCE_OF
8885.long .L_OP_ARRAY_LENGTH
8886.long .L_OP_NEW_INSTANCE
8887.long .L_OP_NEW_ARRAY
8888.long .L_OP_FILLED_NEW_ARRAY
8889.long .L_OP_FILLED_NEW_ARRAY_RANGE
8890.long .L_OP_FILL_ARRAY_DATA
8891.long .L_OP_THROW
8892.long .L_OP_GOTO
8893.long .L_OP_GOTO_16
8894.long .L_OP_GOTO_32
8895.long .L_OP_PACKED_SWITCH
8896.long .L_OP_SPARSE_SWITCH
8897.long .L_OP_CMPL_FLOAT
8898.long .L_OP_CMPG_FLOAT
8899.long .L_OP_CMPL_DOUBLE
8900.long .L_OP_CMPG_DOUBLE
8901.long .L_OP_CMP_LONG
8902.long .L_OP_IF_EQ
8903.long .L_OP_IF_NE
8904.long .L_OP_IF_LT
8905.long .L_OP_IF_GE
8906.long .L_OP_IF_GT
8907.long .L_OP_IF_LE
8908.long .L_OP_IF_EQZ
8909.long .L_OP_IF_NEZ
8910.long .L_OP_IF_LTZ
8911.long .L_OP_IF_GEZ
8912.long .L_OP_IF_GTZ
8913.long .L_OP_IF_LEZ
8914.long .L_OP_UNUSED_3E
8915.long .L_OP_UNUSED_3F
8916.long .L_OP_UNUSED_40
8917.long .L_OP_UNUSED_41
8918.long .L_OP_UNUSED_42
8919.long .L_OP_UNUSED_43
8920.long .L_OP_AGET
8921.long .L_OP_AGET_WIDE
8922.long .L_OP_AGET_OBJECT
8923.long .L_OP_AGET_BOOLEAN
8924.long .L_OP_AGET_BYTE
8925.long .L_OP_AGET_CHAR
8926.long .L_OP_AGET_SHORT
8927.long .L_OP_APUT
8928.long .L_OP_APUT_WIDE
8929.long .L_OP_APUT_OBJECT
8930.long .L_OP_APUT_BOOLEAN
8931.long .L_OP_APUT_BYTE
8932.long .L_OP_APUT_CHAR
8933.long .L_OP_APUT_SHORT
8934.long .L_OP_IGET
8935.long .L_OP_IGET_WIDE
8936.long .L_OP_IGET_OBJECT
8937.long .L_OP_IGET_BOOLEAN
8938.long .L_OP_IGET_BYTE
8939.long .L_OP_IGET_CHAR
8940.long .L_OP_IGET_SHORT
8941.long .L_OP_IPUT
8942.long .L_OP_IPUT_WIDE
8943.long .L_OP_IPUT_OBJECT
8944.long .L_OP_IPUT_BOOLEAN
8945.long .L_OP_IPUT_BYTE
8946.long .L_OP_IPUT_CHAR
8947.long .L_OP_IPUT_SHORT
8948.long .L_OP_SGET
8949.long .L_OP_SGET_WIDE
8950.long .L_OP_SGET_OBJECT
8951.long .L_OP_SGET_BOOLEAN
8952.long .L_OP_SGET_BYTE
8953.long .L_OP_SGET_CHAR
8954.long .L_OP_SGET_SHORT
8955.long .L_OP_SPUT
8956.long .L_OP_SPUT_WIDE
8957.long .L_OP_SPUT_OBJECT
8958.long .L_OP_SPUT_BOOLEAN
8959.long .L_OP_SPUT_BYTE
8960.long .L_OP_SPUT_CHAR
8961.long .L_OP_SPUT_SHORT
8962.long .L_OP_INVOKE_VIRTUAL
8963.long .L_OP_INVOKE_SUPER
8964.long .L_OP_INVOKE_DIRECT
8965.long .L_OP_INVOKE_STATIC
8966.long .L_OP_INVOKE_INTERFACE
8967.long .L_OP_UNUSED_73
8968.long .L_OP_INVOKE_VIRTUAL_RANGE
8969.long .L_OP_INVOKE_SUPER_RANGE
8970.long .L_OP_INVOKE_DIRECT_RANGE
8971.long .L_OP_INVOKE_STATIC_RANGE
8972.long .L_OP_INVOKE_INTERFACE_RANGE
8973.long .L_OP_UNUSED_79
8974.long .L_OP_UNUSED_7A
8975.long .L_OP_NEG_INT
8976.long .L_OP_NOT_INT
8977.long .L_OP_NEG_LONG
8978.long .L_OP_NOT_LONG
8979.long .L_OP_NEG_FLOAT
8980.long .L_OP_NEG_DOUBLE
8981.long .L_OP_INT_TO_LONG
8982.long .L_OP_INT_TO_FLOAT
8983.long .L_OP_INT_TO_DOUBLE
8984.long .L_OP_LONG_TO_INT
8985.long .L_OP_LONG_TO_FLOAT
8986.long .L_OP_LONG_TO_DOUBLE
8987.long .L_OP_FLOAT_TO_INT
8988.long .L_OP_FLOAT_TO_LONG
8989.long .L_OP_FLOAT_TO_DOUBLE
8990.long .L_OP_DOUBLE_TO_INT
8991.long .L_OP_DOUBLE_TO_LONG
8992.long .L_OP_DOUBLE_TO_FLOAT
8993.long .L_OP_INT_TO_BYTE
8994.long .L_OP_INT_TO_CHAR
8995.long .L_OP_INT_TO_SHORT
8996.long .L_OP_ADD_INT
8997.long .L_OP_SUB_INT
8998.long .L_OP_MUL_INT
8999.long .L_OP_DIV_INT
9000.long .L_OP_REM_INT
9001.long .L_OP_AND_INT
9002.long .L_OP_OR_INT
9003.long .L_OP_XOR_INT
9004.long .L_OP_SHL_INT
9005.long .L_OP_SHR_INT
9006.long .L_OP_USHR_INT
9007.long .L_OP_ADD_LONG
9008.long .L_OP_SUB_LONG
9009.long .L_OP_MUL_LONG
9010.long .L_OP_DIV_LONG
9011.long .L_OP_REM_LONG
9012.long .L_OP_AND_LONG
9013.long .L_OP_OR_LONG
9014.long .L_OP_XOR_LONG
9015.long .L_OP_SHL_LONG
9016.long .L_OP_SHR_LONG
9017.long .L_OP_USHR_LONG
9018.long .L_OP_ADD_FLOAT
9019.long .L_OP_SUB_FLOAT
9020.long .L_OP_MUL_FLOAT
9021.long .L_OP_DIV_FLOAT
9022.long .L_OP_REM_FLOAT
9023.long .L_OP_ADD_DOUBLE
9024.long .L_OP_SUB_DOUBLE
9025.long .L_OP_MUL_DOUBLE
9026.long .L_OP_DIV_DOUBLE
9027.long .L_OP_REM_DOUBLE
9028.long .L_OP_ADD_INT_2ADDR
9029.long .L_OP_SUB_INT_2ADDR
9030.long .L_OP_MUL_INT_2ADDR
9031.long .L_OP_DIV_INT_2ADDR
9032.long .L_OP_REM_INT_2ADDR
9033.long .L_OP_AND_INT_2ADDR
9034.long .L_OP_OR_INT_2ADDR
9035.long .L_OP_XOR_INT_2ADDR
9036.long .L_OP_SHL_INT_2ADDR
9037.long .L_OP_SHR_INT_2ADDR
9038.long .L_OP_USHR_INT_2ADDR
9039.long .L_OP_ADD_LONG_2ADDR
9040.long .L_OP_SUB_LONG_2ADDR
9041.long .L_OP_MUL_LONG_2ADDR
9042.long .L_OP_DIV_LONG_2ADDR
9043.long .L_OP_REM_LONG_2ADDR
9044.long .L_OP_AND_LONG_2ADDR
9045.long .L_OP_OR_LONG_2ADDR
9046.long .L_OP_XOR_LONG_2ADDR
9047.long .L_OP_SHL_LONG_2ADDR
9048.long .L_OP_SHR_LONG_2ADDR
9049.long .L_OP_USHR_LONG_2ADDR
9050.long .L_OP_ADD_FLOAT_2ADDR
9051.long .L_OP_SUB_FLOAT_2ADDR
9052.long .L_OP_MUL_FLOAT_2ADDR
9053.long .L_OP_DIV_FLOAT_2ADDR
9054.long .L_OP_REM_FLOAT_2ADDR
9055.long .L_OP_ADD_DOUBLE_2ADDR
9056.long .L_OP_SUB_DOUBLE_2ADDR
9057.long .L_OP_MUL_DOUBLE_2ADDR
9058.long .L_OP_DIV_DOUBLE_2ADDR
9059.long .L_OP_REM_DOUBLE_2ADDR
9060.long .L_OP_ADD_INT_LIT16
9061.long .L_OP_RSUB_INT
9062.long .L_OP_MUL_INT_LIT16
9063.long .L_OP_DIV_INT_LIT16
9064.long .L_OP_REM_INT_LIT16
9065.long .L_OP_AND_INT_LIT16
9066.long .L_OP_OR_INT_LIT16
9067.long .L_OP_XOR_INT_LIT16
9068.long .L_OP_ADD_INT_LIT8
9069.long .L_OP_RSUB_INT_LIT8
9070.long .L_OP_MUL_INT_LIT8
9071.long .L_OP_DIV_INT_LIT8
9072.long .L_OP_REM_INT_LIT8
9073.long .L_OP_AND_INT_LIT8
9074.long .L_OP_OR_INT_LIT8
9075.long .L_OP_XOR_INT_LIT8
9076.long .L_OP_SHL_INT_LIT8
9077.long .L_OP_SHR_INT_LIT8
9078.long .L_OP_USHR_INT_LIT8
9079.long .L_OP_IGET_VOLATILE
9080.long .L_OP_IPUT_VOLATILE
9081.long .L_OP_SGET_VOLATILE
9082.long .L_OP_SPUT_VOLATILE
9083.long .L_OP_IGET_OBJECT_VOLATILE
9084.long .L_OP_IGET_WIDE_VOLATILE
9085.long .L_OP_IPUT_WIDE_VOLATILE
9086.long .L_OP_SGET_WIDE_VOLATILE
9087.long .L_OP_SPUT_WIDE_VOLATILE
9088.long .L_OP_BREAKPOINT
9089.long .L_OP_THROW_VERIFICATION_ERROR
9090.long .L_OP_EXECUTE_INLINE
9091.long .L_OP_EXECUTE_INLINE_RANGE
9092.long .L_OP_INVOKE_DIRECT_EMPTY
9093.long .L_OP_RETURN_VOID_BARRIER
9094.long .L_OP_IGET_QUICK
9095.long .L_OP_IGET_WIDE_QUICK
9096.long .L_OP_IGET_OBJECT_QUICK
9097.long .L_OP_IPUT_QUICK
9098.long .L_OP_IPUT_WIDE_QUICK
9099.long .L_OP_IPUT_OBJECT_QUICK
9100.long .L_OP_INVOKE_VIRTUAL_QUICK
9101.long .L_OP_INVOKE_VIRTUAL_QUICK_RANGE
9102.long .L_OP_INVOKE_SUPER_QUICK
9103.long .L_OP_INVOKE_SUPER_QUICK_RANGE
9104.long .L_OP_IPUT_OBJECT_VOLATILE
9105.long .L_OP_SGET_OBJECT_VOLATILE
9106.long .L_OP_SPUT_OBJECT_VOLATILE
9107.long .L_OP_UNUSED_FF
9108
9109
9110/* File: x86/footer.S */
9111/*
9112 * Copyright (C) 2008 The Android Open Source Project
9113 *
9114 * Licensed under the Apache License, Version 2.0 (the "License");
9115 * you may not use this file except in compliance with the License.
9116 * You may obtain a copy of the License at
9117 *
9118 *      http://www.apache.org/licenses/LICENSE-2.0
9119 *
9120 * Unless required by applicable law or agreed to in writing, software
9121 * distributed under the License is distributed on an "AS IS" BASIS,
9122 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9123 * See the License for the specific language governing permissions and
9124 * limitations under the License.
9125 */
9126/*
9127 * Common subroutines and data.
9128 */
9129
9130#if defined(WITH_JIT)
9131/*
9132 * Placeholder entries for x86 JIT
9133 */
9134    .global dvmJitToInterpPunt
9135dvmJitToInterpPunt:
9136    .global dvmJitToInterpSingleStep
9137dvmJitToInterpSingleStep:
9138    .global dvmJitToInterpNoChainNoProfile
9139dvmJitToInterpNoChainNoProfile:
9140    .global dvmJitToInterpTraceSelectNoChain
9141dvmJitToInterpTraceSelectNoChain:
9142    .global dvmJitToInterpTraceSelect
9143dvmJitToInterpTraceSelect:
9144    .global dvmJitToInterpBackwardBranch
9145dvmJitToInterpBackwardBranch:
9146    .global dvmJitToInterpNormal
9147dvmJitToInterpNormal:
9148    .global dvmJitToInterpNoChain
9149dvmJitToInterpNoChain:
9150    jmp  common_abort
9151#endif
9152
9153/*
9154 * Common code when a backwards branch is taken
9155 *
9156 * On entry:
9157 *   ebx (a.k.a. rINST) -> PC adjustment in 16-bit words
9158 */
9159common_backwardBranch:
9160    movl    rGLUE,%ecx
9161    call   common_periodicChecks  # Note: expects rPC to be preserved
9162    ADVANCE_PC_INDEXED rINST
9163    FETCH_INST
9164    GOTO_NEXT
9165
9166
9167
9168/*
9169 * Common code for method invocation with range.
9170 *
9171 * On entry:
9172 *   eax = Method* methodToCall
9173 *   rINSTw trashed, must reload
9174 */
9175
9176common_invokeMethodRange:
9177.LinvokeNewRange:
9178
9179   /*
9180    * prepare to copy args to "outs" area of current frame
9181    */
9182
9183    movzbl      1(rPC),rINST       # rINST<- AA
9184    movzwl      4(rPC), %ecx            # %ecx<- CCCC
9185    SAVEAREA_FROM_FP %edx               # %edx<- &StackSaveArea
9186    test        rINST, rINST
9187    movl        rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
9188    jz          .LinvokeArgsDone        # no args; jump to args done
9189
9190
9191   /*
9192    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
9193    * (very few methods have > 10 args; could unroll for common cases)
9194    */
9195
9196    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
9197    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
9198    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
9199    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
9200    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
92011:
9202    movl        (%ecx), %ebx            # %ebx<- vCCCC
9203    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
9204    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
9205    movl        %ebx, (%edx)            # *outs<- vCCCC
9206    lea         4(%edx), %edx           # outs++
9207    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
9208    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
9209    jmp         .LinvokeArgsDone        # continue
9210
9211   /*
9212    * %eax is "Method* methodToCall", the method we're trying to call
9213    * prepare to copy args to "outs" area of current frame
9214    */
9215
9216common_invokeMethodNoRange:
9217.LinvokeNewNoRange:
9218    movzbl      1(rPC),rINST       # rINST<- BA
9219    movl        rINST, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
9220    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
9221    je          .LinvokeArgsDone        # no args; jump to args done
9222    movzwl      4(rPC), %ecx            # %ecx<- GFED
9223    SAVEAREA_FROM_FP %edx               # %edx<- &StackSaveArea
9224
9225   /*
9226    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
9227    */
9228
9229.LinvokeNonRange:
9230    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
9231    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
9232    jl          1f                      # handle 1 arg
9233    je          2f                      # handle 2 args
9234    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
9235    jl          3f                      # handle 3 args
9236    je          4f                      # handle 4 args
92375:
9238    andl        $15, rINST             # rINSTw<- A
9239    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9240    movl        (rFP, rINST, 4), %ecx   # %ecx<- vA
9241    movl        %ecx, (%edx)            # *outs<- vA
9242    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92434:
9244    shr         $12, %ecx              # %ecx<- G
9245    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9246    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
9247    movl        %ecx, (%edx)            # *outs<- vG
9248    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92493:
9250    and         $0x0f00, %ecx          # %ecx<- 0F00
9251    shr         $8, %ecx               # %ecx<- F
9252    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9253    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
9254    movl        %ecx, (%edx)            # *outs<- vF
9255    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92562:
9257    and         $0x00f0, %ecx          # %ecx<- 00E0
9258    shr         $4, %ecx               # %ecx<- E
9259    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9260    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
9261    movl        %ecx, (%edx)            # *outs<- vE
9262    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
92631:
9264    and         $0x000f, %ecx          # %ecx<- 000D
9265    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
9266    movl        %ecx, -4(%edx)          # *--outs<- vD
92670:
9268
9269   /*
9270    * %eax is "Method* methodToCall", the method we're trying to call
9271    * find space for the new stack frame, check for overflow
9272    */
9273
9274.LinvokeArgsDone:
9275    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
9276    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
9277    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
9278    shl         $2, %edx               # %edx<- update offset
9279    SAVEAREA_FROM_FP %eax               # %eax<- &StackSaveArea
9280    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
9281    movl        rGLUE,%edx              # %edx<- pMterpGlue
9282    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
9283    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
9284    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
9285    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
9286    shl         $2, %ecx               # %ecx<- update offset for outsSize
9287    movl        %eax, %edx              # %edx<- newSaveArea
9288    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
9289    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
9290    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
9291    jl          .LstackOverflow         # handle frame overflow
9292
9293   /*
9294    * set up newSaveArea
9295    */
9296
9297#ifdef EASY_GDB
9298    SAVEAREA_FROM_FP %ecx               # %ecx<- &StackSaveArea
9299    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
9300#endif
9301    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
9302    movl        rPC, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
9303    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
9304    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
9305    jne         .LinvokeNative          # handle native call
9306
9307   /*
9308    * Update "glue" values for the new method
9309    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
9310    */
9311
9312    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
9313    movl        rGLUE,%ecx                  # %ecx<- pMterpGlue
9314    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
9315    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
9316    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
9317    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
9318    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
9319    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
9320    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
9321    FETCH_INST
9322    GOTO_NEXT                           # jump to methodToCall->insns
9323
9324   /*
9325    * Prep for the native call
9326    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
9327    */
9328
9329.LinvokeNative:
9330    movl        rGLUE,%ecx              # %ecx<- pMterpGlue
9331    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9332    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
9333    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
9334    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
9335    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
9336    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
9337    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
9338    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
9339    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
9340    movl        rGLUE,%ecx              # %ecx<- pMterpGlue
9341    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
9342    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
9343    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
9344    push        %edx                    # push parameter newFP
9345
9346    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
9347    lea         4(%esp), %esp
9348    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
9349    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
9350    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
9351    cmp         $0, offThread_exception(%eax) # check for exception
9352    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
9353    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
9354    jne         common_exceptionThrown  # handle exception
9355    FETCH_INST_OPCODE 3 %edx
9356    ADVANCE_PC 3
9357    GOTO_NEXT_R %edx                    # jump to next instruction
9358
9359.LstackOverflow:    # eax=methodToCall
9360    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9361    movl        rGLUE,%eax              # %eax<- pMterpGlue
9362    movl        offGlue_self(%eax), %eax # %eax<- glue->self
9363    movl        %eax, OUT_ARG0(%esp)    # push parameter self
9364    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
9365    jmp         common_exceptionThrown  # handle exception
9366
9367
9368/*
9369 * Do we need the thread to be suspended or have debugger/profiling activity?
9370 *
9371 * On entry:
9372 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
9373 *   ecx  -> GLUE pointer
9374 *   reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint
9375 *
9376 * Note: A call will normally kill %eax and %ecx.  To
9377 *       streamline the normal case, this routine will preserve
9378 *       %ecx in addition to the normal caller save regs.  The save/restore
9379 *       is a bit ugly, but will happen in the relatively uncommon path.
9380 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
9381 *       the suspendCount check so we can get both in 1 shot.
9382 */
9383common_periodicChecks:
9384    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
9385    cmpl    $0,(%eax)
9386    jne     1f
9387
93886:
9389    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
9390    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
9391    testl  %eax,%eax               # debugger enabled?
9392    je     2f
9393    movzbl (%eax),%eax             # get active count
93942:
9395    orl    (%ecx),%eax             # eax <- debuggerActive | activeProfilers
9396    movl   rGLUE,%ecx              # restore rGLUE
9397    jne    3f                      # one or both active - switch interp
9398
93995:
9400    ret
9401
9402    /* Check for suspend */
94031:
9404    /*  At this point, the return pointer to the caller of
9405     *  common_periodicChecks is on the top of stack.  We need to preserve
9406     *  GLUE(ecx).
9407     *  The outgoing profile is:
9408     *      bool dvmCheckSuspendPending(Thread* self)
9409     *  Because we reached here via a call, go ahead and build a new frame.
9410     */
9411    EXPORT_PC                         # need for precise GC
9412    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
9413    push    %ebp
9414    movl    %esp,%ebp
9415    subl    $24,%esp
9416    movl    %eax,OUT_ARG0(%esp)
9417    call    dvmCheckSuspendPending
9418    addl    $24,%esp
9419    pop     %ebp
9420    movl    rGLUE,%ecx
9421
9422    /*
9423     * Need to check to see if debugger or profiler flags got set
9424     * while we were suspended.
9425     */
9426    jmp    6b
9427
9428    /* Switch interpreters */
9429    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
9430     * "complete" the interpretation of backwards branches.  In effect, we
9431     * are completing the interpretation of the branch instruction here,
9432     * and the new interpreter will resume interpretation at the branch
9433     * target. However, a switch request recognized during the handling
9434     * of a return from method instruction results in an immediate abort,
9435     * and the new interpreter will resume by re-interpreting the return
9436     * instruction.
9437     */
94383:
9439    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
9440    movl    rGLUE,%ecx             # bail expect GLUE already loaded
9441    movl    $1,rINST              # set changeInterp to true
9442    jmp     common_gotoBail
9443
9444
9445/*
9446 * Common code for handling a return instruction
9447 */
9448common_returnFromMethod:
9449    movl    rGLUE,%ecx
9450    /* Set entry mode in case we bail */
9451    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
9452    xorl    rINST,rINST   # zero offset in case we switch interps
9453    call    common_periodicChecks   # Note: expects %ecx to be preserved
9454
9455    SAVEAREA_FROM_FP %eax                         # eax<- saveArea (old)
9456    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
9457    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST
9458    cmpl    $0,rINST                             # break?
9459    je      common_gotoBail    # break frame, bail out completely
9460
9461    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
9462    movl    offGlue_self(%ecx),%eax               # eax<- self
9463    movl    rINST,offGlue_method(%ecx)  # glue->method = newSave->meethod
9464    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
9465    movl    offMethod_clazz(rINST),%eax      # eax<- method->clazz
9466    FETCH_INST_OPCODE 3 %edx
9467    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
9468    ADVANCE_PC 3
9469    movl    %eax,offGlue_methodClassDex(%ecx)
9470    /* not bailing - restore entry mode to default */
9471    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
9472    GOTO_NEXT_R %edx
9473
9474/*
9475 * Prepare to strip the current frame and "longjump" back to caller of
9476 * dvmMterpStdRun.
9477 *
9478 * on entry:
9479 *    rINST holds changeInterp
9480 *    ecx holds glue pointer
9481 *
9482 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
9483 */
9484common_gotoBail:
9485    movl   rPC,offGlue_pc(%ecx)     # export state to glue
9486    movl   rFP,offGlue_fp(%ecx)
9487    movl   %ecx,OUT_ARG0(%esp)      # glue in arg0
9488    movl   rINST,OUT_ARG1(%esp)     # changeInterp in arg1
9489    call   dvmMterpStdBail          # bail out....
9490
9491
9492/*
9493 * After returning from a "glued" function, pull out the updated values
9494 * and start executing at the next instruction.
9495 */
9496 common_resumeAfterGlueCall:
9497     LOAD_PC_FP_FROM_GLUE
9498     FETCH_INST
9499     GOTO_NEXT
9500
9501/*
9502 * Integer divide or mod by zero
9503 */
9504common_errDivideByZero:
9505    EXPORT_PC
9506    movl    $.LstrArithmeticException,%eax
9507    movl    %eax,OUT_ARG0(%esp)
9508    movl    $.LstrDivideByZero,%eax
9509    movl    %eax,OUT_ARG1(%esp)
9510    call    dvmThrowException
9511    jmp     common_exceptionThrown
9512
9513/*
9514 * Attempt to allocate an array with a negative size.
9515 */
9516common_errNegativeArraySize:
9517    EXPORT_PC
9518    movl    $.LstrNegativeArraySizeException,%eax
9519    movl    %eax,OUT_ARG0(%esp)
9520    xorl    %eax,%eax
9521    movl    %eax,OUT_ARG1(%esp)
9522    call    dvmThrowException
9523    jmp     common_exceptionThrown
9524
9525/*
9526 * Attempt to allocate an array with a negative size.
9527 */
9528common_errNoSuchMethod:
9529
9530    EXPORT_PC
9531    movl    $.LstrNoSuchMethodError,%eax
9532    movl    %eax,OUT_ARG0(%esp)
9533    xorl    %eax,%eax
9534    movl    %eax,OUT_ARG1(%esp)
9535    call    dvmThrowException
9536    jmp     common_exceptionThrown
9537
9538/*
9539 * Hit a null object when we weren't expecting one.  Export the PC, throw a
9540 * NullPointerException and goto the exception processing code.
9541 */
9542common_errNullObject:
9543    EXPORT_PC
9544    movl    $.LstrNullPointerException,%eax
9545    movl    %eax,OUT_ARG0(%esp)
9546    xorl    %eax,%eax
9547    movl    %eax,OUT_ARG1(%esp)
9548    call    dvmThrowException
9549    jmp     common_exceptionThrown
9550
9551/*
9552 * Array index exceeds max.
9553 * On entry:
9554 *    eax <- array object
9555 *    ecx <- index
9556 */
9557common_errArrayIndex:
9558    EXPORT_PC
9559    movl    offArrayObject_length(%eax), %eax
9560    movl    %ecx,OUT_ARG0(%esp)
9561    movl    %eax,OUT_ARG1(%esp)
9562    call    dvmThrowAIOOBE        # dvmThrowAIOO(index, length)
9563    jmp     common_exceptionThrown
9564
9565/*
9566 * Somebody has thrown an exception.  Handle it.
9567 *
9568 * If the exception processing code returns to us (instead of falling
9569 * out of the interpreter), continue with whatever the next instruction
9570 * now happens to be.
9571 *
9572 * This does not return.
9573 */
9574common_exceptionThrown:
9575    movl    rGLUE,%ecx
9576    movl    rPC,offGlue_pc(%ecx)
9577    movl    rFP,offGlue_fp(%ecx)
9578    movl    %ecx,OUT_ARG0(%esp)
9579    call    dvmMterp_exceptionThrown
9580    jmp     common_resumeAfterGlueCall
9581
9582common_abort:
9583    movl    $0xdeadf00d,%eax
9584    call     *%eax
9585
9586
9587/*
9588 * Strings
9589 */
9590
9591    .section     .rodata
9592.LstrNullPointerException:
9593    .asciz    "Ljava/lang/NullPointerException;"
9594.LstrArithmeticException:
9595    .asciz  "Ljava/lang/ArithmeticException;"
9596.LstrDivideByZero:
9597    .asciz  "divide by zero"
9598.LstrNegativeArraySizeException:
9599    .asciz  "Ljava/lang/NegativeArraySizeException;"
9600.LstrInstantiationError:
9601    .asciz  "Ljava/lang/InstantiationError;"
9602.LstrNoSuchMethodError:
9603    .asciz  "Ljava/lang/NoSuchMethodError;"
9604.LstrInternalErrorA:
9605    .asciz  "Ljava/lang/InternalError;"
9606.LstrFilledNewArrayNotImplA:
9607    .asciz  "filled-new-array only implemented for 'int'"
9608
9609