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