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