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