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