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