OSDN Git Service

x86 mterp: reduce x86/x86-atom differences
[android-x86/dalvik.git] / vm / mterp / out / InterpAsm-x86.S
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 /*
28 386 ABI general notes:
29
30 Caller save set:
31    eax, edx, ecx, st(0)-st(7)
32 Callee save set:
33    ebx, esi, edi, ebp
34 Return 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
39 Parameters passed on stack, pushed right-to-left.  On entry to target, first
40 parm is at 4(%esp).  Traditional entry code is:
41
42 functEntry:
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
47 Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)
48
49 Alignment of stack not strictly required, but should be for performance.  We'll
50 align frame sizes to 16-byte multiples.
51
52 If we're not doing variable stack allocation (alloca), the frame pointer can be
53 eliminated and all arg references adjusted to be esp relative.
54
55 Mterp notes:
56
57 Some key interpreter variables will be assigned to registers.  Note that each
58 will also have an associated spill location (mostly used useful for those assigned
59 to callee save registers).
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
68 Notes:
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
599 dvmAsmInstructionStart = .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
1565 1:
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
1595 1:
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
1625 1:
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
1655 1:
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
1685 1:
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
1715 1:
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
1741 1:
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
1767 1:
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
1793 1:
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
1819 1:
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
1845 1:
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
1871 1:
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 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)
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
4306 2:
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
4338 2:
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
4370 2:
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
4470 1:
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
4575 1:
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
5070 2:
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
5098 2:
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
5126 2:
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
5233 1:
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
5346 1:
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
6416 dvmAsmInstructionEnd:
6417
6418 /*
6419  * ===========================================================================
6420  *  Sister implementations
6421  * ===========================================================================
6422  */
6423     .global dvmAsmSisterStart
6424     .type   dvmAsmSisterStart, %function
6425     .text
6426     .balign 4
6427 dvmAsmSisterStart:
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
6766 1:
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
6809 3:
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
6818 4:
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
6830 5:
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
6876 1:
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
6919 3:
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
6928 4:
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
6940 5:
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
7380 1:
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
7682 1:
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     FETCH_INST_OPCODE 2 %ecx
8156     UNSPILL_TMP2(%esi)
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
8588 1:
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
8627 1:
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
8661 1:
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
8680 dvmAsmSisterEnd:
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  */
8709 dvmMterpStdRun:
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  */
8776 dvmMterpStdBail:
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 */
8803 dvmAsmInstructionJmpTable = .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
9088 dvmJitToInterpPunt:
9089     .global dvmJitToInterpSingleStep
9090 dvmJitToInterpSingleStep:
9091     .global dvmJitToInterpNoChainNoProfile
9092 dvmJitToInterpNoChainNoProfile:
9093     .global dvmJitToInterpTraceSelectNoChain
9094 dvmJitToInterpTraceSelectNoChain:
9095     .global dvmJitToInterpTraceSelect
9096 dvmJitToInterpTraceSelect:
9097     .global dvmJitToInterpBackwardBranch
9098 dvmJitToInterpBackwardBranch:
9099     .global dvmJitToInterpNormal
9100 dvmJitToInterpNormal:
9101     .global dvmJitToInterpNoChain
9102 dvmJitToInterpNoChain:
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  */
9112 common_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
9129 common_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
9154 1:
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
9169 common_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
9190 5:
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
9196 4:
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
9202 3:
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
9209 2:
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
9216 1:
9217     and         $0x000f, %ecx          # %ecx<- 000D
9218     movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
9219     movl        %ecx, -4(%edx)          # *--outs<- vD
9220 0:
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  */
9336 common_periodicChecks:
9337     movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
9338     cmpl    $0,(%eax)
9339     jne     1f
9340
9341 6:
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
9347 2:
9348     orl    (%ecx),%eax             # eax <- debuggerActive | activeProfilers
9349     movl   rGLUE,%ecx              # restore rGLUE
9350     jne    3f                      # one or both active - switch interp
9351
9352 5:
9353     ret
9354
9355     /* Check for suspend */
9356 1:
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      */
9391 3:
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  */
9401 common_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  */
9437 common_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  */
9457 common_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  */
9469 common_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  */
9481 common_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  */
9495 common_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  */
9507 common_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  */
9518 common_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  */
9536 common_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
9544 common_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