InterpAsm-x86.S revision 4c1a2915e40eceeb68dbc323d28b8bf8763af83b
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    %ecx,OUT_ARG0(%esp)                   # arg0<- typeCh
6547    cmpb    $'I',%cl                             # supported?
6548    jne      .LOP_FILLED_NEW_ARRAY_notimpl                  # no, not handled yet
6549    .if      (!0)
6550    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
6551    sarl    $4,rINST_FULL
6552    .endif
6553    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
6554    call    dvmAllocPrimitiveArray      # eax<- call(typeCh, length, flags)
6555    UNSPILL(rPC)
6556    GET_GLUE(%ecx)
6557    testl   %eax,%eax                             # alloc successful?
6558    je      common_exceptionThrown                # no, handle exception
6559    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6560    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6561    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6562
6563/* at this point:
6564 *     eax is pointer to tgt
6565 *     rINST_FULL is length
6566 *     ecx is FEDC or CCCC
6567 *     TMP_SPILL is BA
6568 *     rPC is valid, but spilled
6569 *  We now need to copy values from registers into the array
6570 */
6571
6572    .if 0
6573    # set up src pointer
6574    SPILL(rFP)     # esi
6575    SPILL(rIBASE)   # edi
6576    movl    %eax,%edi         # set up dst ptr
6577    leal    (rFP,%ecx,4),%esi # set up src ptr
6578    movl    rINST_FULL,%ecx   # load count register
6579    FETCH_INST_WORD(3)
6580    rep
6581    movsd
6582    UNSPILL(rIBASE)
6583    UNSPILL(rFP)
6584    .else
6585    testl  rINST_FULL,rINST_FULL
6586    je     4f
6587    UNSPILL_TMP(rPC)
6588    andl   $0x0f,rPC            # rPC<- 0000000A
6589    sall   $16,rPC              # rPC<- 000A0000
6590    orl    %ecx,rPC              # rpc<- 000AFEDC
65913:
6592    movl   $0xf,%ecx
6593    andl   rPC,%ecx           # ecx<- next reg to load
6594    GET_VREG(%ecx,%ecx)
6595    shrl   $4,rPC
6596    leal   4(%eax),%eax
6597    movl   %ecx,-4(%eax)
6598    sub    $1,rINST_FULL
6599    jne    3b
66004:
6601    UNSPILL(rPC)
6602    FETCH_INST_WORD(3)
6603    .endif
6604
6605    ADVANCE_PC(3)
6606    GOTO_NEXT
6607
6608
6609    /*
6610     * Throw an exception indicating that we have not implemented this
6611     * mode of filled-new-array.
6612     */
6613.LOP_FILLED_NEW_ARRAY_notimpl:
6614    movl    $.LstrInternalError,%eax
6615    movl    %eax,OUT_ARG0(%esp)
6616    movl    $.LstrFilledNewArrayNotImpl,%eax
6617    movl    %eax,OUT_ARG1(%esp)
6618    call    dvmThrowException
6619    UNSPILL(rPC)
6620    jmp     common_exceptionThrown
6621
6622
6623/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6624
6625.LOP_FILLED_NEW_ARRAY_RANGE_more:
6626    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6627    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6628    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6629    UNSPILL(rPC)
6630    testl   %eax,%eax                         # null?
6631    je      common_exceptionThrown            # yes, handle it
6632
6633       # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6634
6635    /*
6636     * On entry:
6637     *    eax holds array class [r0]
6638     *    rINST_FULL holds AA or BB [r10]
6639     *    ecx is scratch
6640     *    rPC is valid, but has been spilled
6641     */
6642.LOP_FILLED_NEW_ARRAY_RANGE_continue:
6643    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6644    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6645    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6646    movl    %ecx,OUT_ARG0(%esp)                   # arg0<- typeCh
6647    cmpb    $'I',%cl                             # supported?
6648    jne      .LOP_FILLED_NEW_ARRAY_RANGE_notimpl                  # no, not handled yet
6649    .if      (!1)
6650    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
6651    sarl    $4,rINST_FULL
6652    .endif
6653    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
6654    call    dvmAllocPrimitiveArray      # eax<- call(typeCh, length, flags)
6655    UNSPILL(rPC)
6656    GET_GLUE(%ecx)
6657    testl   %eax,%eax                             # alloc successful?
6658    je      common_exceptionThrown                # no, handle exception
6659    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6660    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6661    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6662
6663/* at this point:
6664 *     eax is pointer to tgt
6665 *     rINST_FULL is length
6666 *     ecx is FEDC or CCCC
6667 *     TMP_SPILL is BA
6668 *     rPC is valid, but spilled
6669 *  We now need to copy values from registers into the array
6670 */
6671
6672    .if 1
6673    # set up src pointer
6674    SPILL(rFP)     # esi
6675    SPILL(rIBASE)   # edi
6676    movl    %eax,%edi         # set up dst ptr
6677    leal    (rFP,%ecx,4),%esi # set up src ptr
6678    movl    rINST_FULL,%ecx   # load count register
6679    FETCH_INST_WORD(3)
6680    rep
6681    movsd
6682    UNSPILL(rIBASE)
6683    UNSPILL(rFP)
6684    .else
6685    testl  rINST_FULL,rINST_FULL
6686    je     4f
6687    UNSPILL_TMP(rPC)
6688    andl   $0x0f,rPC            # rPC<- 0000000A
6689    sall   $16,rPC              # rPC<- 000A0000
6690    orl    %ecx,rPC              # rpc<- 000AFEDC
66913:
6692    movl   $0xf,%ecx
6693    andl   rPC,%ecx           # ecx<- next reg to load
6694    GET_VREG(%ecx,%ecx)
6695    shrl   $4,rPC
6696    leal   4(%eax),%eax
6697    movl   %ecx,-4(%eax)
6698    sub    $1,rINST_FULL
6699    jne    3b
67004:
6701    UNSPILL(rPC)
6702    FETCH_INST_WORD(3)
6703    .endif
6704
6705    ADVANCE_PC(3)
6706    GOTO_NEXT
6707
6708
6709    /*
6710     * Throw an exception indicating that we have not implemented this
6711     * mode of filled-new-array.
6712     */
6713.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6714    movl    $.LstrInternalError,%eax
6715    movl    %eax,OUT_ARG0(%esp)
6716    movl    $.LstrFilledNewArrayNotImpl,%eax
6717    movl    %eax,OUT_ARG1(%esp)
6718    call    dvmThrowException
6719    UNSPILL(rPC)
6720    jmp     common_exceptionThrown
6721
6722
6723/* continuation for OP_CMPL_FLOAT */
6724
6725.LOP_CMPL_FLOAT_isNaN:
6726    movl      $-1,%ecx
6727    jmp       .LOP_CMPL_FLOAT_finish
6728
6729/* continuation for OP_CMPG_FLOAT */
6730
6731.LOP_CMPG_FLOAT_isNaN:
6732    movl      $1,%ecx
6733    jmp       .LOP_CMPG_FLOAT_finish
6734
6735/* continuation for OP_CMPL_DOUBLE */
6736
6737.LOP_CMPL_DOUBLE_isNaN:
6738    movl      $-1,%ecx
6739    jmp       .LOP_CMPL_DOUBLE_finish
6740
6741/* continuation for OP_CMPG_DOUBLE */
6742
6743.LOP_CMPG_DOUBLE_isNaN:
6744    movl      $1,%ecx
6745    jmp       .LOP_CMPG_DOUBLE_finish
6746
6747/* continuation for OP_CMP_LONG */
6748
6749.LOP_CMP_LONG_bigger:
6750    UNSPILL(rPC)
6751    movl      $1,%ecx
6752    jmp       .LOP_CMP_LONG_finish
6753.LOP_CMP_LONG_smaller:
6754    UNSPILL(rPC)
6755    movl      $-1,%ecx
6756.LOP_CMP_LONG_finish:
6757    SET_VREG(%ecx,rINST_FULL)
6758    FETCH_INST_WORD(2)
6759    ADVANCE_PC(2)
6760    GOTO_NEXT
6761
6762/* continuation for OP_AGET_WIDE */
6763
6764.LOP_AGET_WIDE_finish:
6765    leal      offArrayObject_contents(%eax,%ecx,8),%eax
6766    movl      (%eax),%ecx
6767    movl      4(%eax),%eax
6768    SET_VREG_WORD(%ecx,rINST_FULL,0)
6769    SET_VREG_WORD(%eax,rINST_FULL,1)
6770    FETCH_INST_WORD(2)
6771    ADVANCE_PC(2)
6772    GOTO_NEXT
6773
6774
6775/* continuation for OP_APUT_WIDE */
6776
6777.LOP_APUT_WIDE_finish:
6778    leal      offArrayObject_contents(%eax,%ecx,8),%eax
6779    GET_VREG_WORD(%ecx,rINST_FULL,0)
6780    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)
6781    movl      rINST_FULL,4(%eax)
6782    FETCH_INST_WORD(2)
6783    movl      %ecx,(%eax)
6784    ADVANCE_PC(2)
6785    GOTO_NEXT
6786
6787
6788/* continuation for OP_APUT_OBJECT */
6789
6790    /* On entry:
6791     *   eax<- array object
6792     *   ecx<- index
6793     *   rINST_FULL<- vAA
6794     */
6795.LOP_APUT_OBJECT_continue:
6796    leal      offArrayObject_contents(%eax,%ecx,4),%ecx
6797    testl     rINST_FULL,rINST_FULL     # storing null reference?
6798    je        .LOP_APUT_OBJECT_skip_check
6799    SPILL(rPC)
6800    SPILL_TMP(%ecx)
6801    movl      offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
6802    movl      offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6803    movl      %eax,OUT_ARG1(%esp)
6804    movl      %ecx,OUT_ARG0(%esp)
6805    call      dvmCanPutArrayElement     # test object type vs. array type
6806    UNSPILL(rPC)
6807    UNSPILL_TMP(%ecx)
6808    testl     %eax,%eax
6809    je        common_errArrayStore
6810
6811.LOP_APUT_OBJECT_skip_check:
6812    movl      rINST_FULL,(%ecx)
6813    FETCH_INST_WORD(2)
6814    ADVANCE_PC(2)
6815    GOTO_NEXT
6816
6817
6818/* continuation for OP_IGET */
6819
6820
6821.LOP_IGET_resolve:
6822    EXPORT_PC()
6823    SPILL(rPC)
6824    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6825    UNSPILL(rIBASE)
6826    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6827    SPILL_TMP(%ecx)                               # save object pointer across call
6828    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6829    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6830    UNSPILL_TMP(%ecx)
6831    UNSPILL(rPC)
6832    testl   %eax,%eax                             #  ... which returns InstrField ptr
6833    jne     .LOP_IGET_finish
6834    jmp     common_exceptionThrown
6835
6836.LOP_IGET_finish:
6837    /*
6838     * Currently:
6839     *   eax holds resolved field
6840     *   ecx holds object
6841     *   rIBASE is scratch, but needs to be unspilled
6842     *   rINST_FULL holds A
6843     */
6844    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6845    UNSPILL(rIBASE)
6846    testl   %ecx,%ecx                            # object null?
6847    je      common_errNullObject                 # object was null
6848    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
6849    movl    rINST_FULL,%eax                      # eax<- A
6850    FETCH_INST_WORD(2)
6851    SET_VREG(%ecx,%eax)
6852    ADVANCE_PC(2)
6853    GOTO_NEXT
6854
6855
6856/* continuation for OP_IGET_WIDE */
6857
6858
6859.LOP_IGET_WIDE_resolve:
6860    EXPORT_PC()
6861    SPILL(rPC)
6862    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6863    UNSPILL(rIBASE)
6864    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6865    SPILL_TMP(%ecx)                               # save object pointer across call
6866    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6867    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6868    UNSPILL_TMP(%ecx)
6869    UNSPILL(rPC)
6870    testl   %eax,%eax                             #  ... which returns InstrField ptr
6871    jne     .LOP_IGET_WIDE_finish
6872    jmp     common_exceptionThrown
6873
6874.LOP_IGET_WIDE_finish:
6875    /*
6876     * Currently:
6877     *   eax holds resolved field
6878     *   ecx holds object
6879     *   rIBASE is scratch, but needs to be unspilled
6880     *   rINST_FULL holds A
6881     */
6882    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6883    UNSPILL(rIBASE)
6884    testl   %ecx,%ecx                            # object null?
6885    je      common_errNullObject                 # object was null
6886    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
6887    movl    (%eax),%ecx                          # ecx<- lsw
6888    movl    4(%eax),%eax                         # eax<- msw
6889    SET_VREG_WORD(%ecx,rINST_FULL,0)
6890    SET_VREG_WORD(%eax,rINST_FULL,1)
6891    FETCH_INST_WORD(2)
6892    ADVANCE_PC(2)
6893    GOTO_NEXT
6894
6895
6896/* continuation for OP_IGET_OBJECT */
6897
6898
6899.LOP_IGET_OBJECT_resolve:
6900    EXPORT_PC()
6901    SPILL(rPC)
6902    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6903    UNSPILL(rIBASE)
6904    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6905    SPILL_TMP(%ecx)                               # save object pointer across call
6906    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6907    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6908    UNSPILL_TMP(%ecx)
6909    UNSPILL(rPC)
6910    testl   %eax,%eax                             #  ... which returns InstrField ptr
6911    jne     .LOP_IGET_OBJECT_finish
6912    jmp     common_exceptionThrown
6913
6914.LOP_IGET_OBJECT_finish:
6915    /*
6916     * Currently:
6917     *   eax holds resolved field
6918     *   ecx holds object
6919     *   rIBASE is scratch, but needs to be unspilled
6920     *   rINST_FULL holds A
6921     */
6922    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6923    UNSPILL(rIBASE)
6924    testl   %ecx,%ecx                            # object null?
6925    je      common_errNullObject                 # object was null
6926    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
6927    movl    rINST_FULL,%eax                      # eax<- A
6928    FETCH_INST_WORD(2)
6929    SET_VREG(%ecx,%eax)
6930    ADVANCE_PC(2)
6931    GOTO_NEXT
6932
6933
6934/* continuation for OP_IGET_BOOLEAN */
6935
6936
6937.LOP_IGET_BOOLEAN_resolve:
6938    EXPORT_PC()
6939    SPILL(rPC)
6940    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6941    UNSPILL(rIBASE)
6942    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6943    SPILL_TMP(%ecx)                               # save object pointer across call
6944    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6945    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6946    UNSPILL_TMP(%ecx)
6947    UNSPILL(rPC)
6948    testl   %eax,%eax                             #  ... which returns InstrField ptr
6949    jne     .LOP_IGET_BOOLEAN_finish
6950    jmp     common_exceptionThrown
6951
6952.LOP_IGET_BOOLEAN_finish:
6953    /*
6954     * Currently:
6955     *   eax holds resolved field
6956     *   ecx holds object
6957     *   rIBASE is scratch, but needs to be unspilled
6958     *   rINST_FULL holds A
6959     */
6960    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6961    UNSPILL(rIBASE)
6962    testl   %ecx,%ecx                            # object null?
6963    je      common_errNullObject                 # object was null
6964    movzbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
6965    movl    rINST_FULL,%eax                      # eax<- A
6966    FETCH_INST_WORD(2)
6967    SET_VREG(%ecx,%eax)
6968    ADVANCE_PC(2)
6969    GOTO_NEXT
6970
6971
6972/* continuation for OP_IGET_BYTE */
6973
6974
6975.LOP_IGET_BYTE_resolve:
6976    EXPORT_PC()
6977    SPILL(rPC)
6978    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6979    UNSPILL(rIBASE)
6980    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6981    SPILL_TMP(%ecx)                               # save object pointer across call
6982    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6983    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6984    UNSPILL_TMP(%ecx)
6985    UNSPILL(rPC)
6986    testl   %eax,%eax                             #  ... which returns InstrField ptr
6987    jne     .LOP_IGET_BYTE_finish
6988    jmp     common_exceptionThrown
6989
6990.LOP_IGET_BYTE_finish:
6991    /*
6992     * Currently:
6993     *   eax holds resolved field
6994     *   ecx holds object
6995     *   rIBASE is scratch, but needs to be unspilled
6996     *   rINST_FULL holds A
6997     */
6998    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6999    UNSPILL(rIBASE)
7000    testl   %ecx,%ecx                            # object null?
7001    je      common_errNullObject                 # object was null
7002    movsbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7003    movl    rINST_FULL,%eax                      # eax<- A
7004    FETCH_INST_WORD(2)
7005    SET_VREG(%ecx,%eax)
7006    ADVANCE_PC(2)
7007    GOTO_NEXT
7008
7009
7010/* continuation for OP_IGET_CHAR */
7011
7012
7013.LOP_IGET_CHAR_resolve:
7014    EXPORT_PC()
7015    SPILL(rPC)
7016    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7017    UNSPILL(rIBASE)
7018    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7019    SPILL_TMP(%ecx)                               # save object pointer across call
7020    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7021    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7022    UNSPILL_TMP(%ecx)
7023    UNSPILL(rPC)
7024    testl   %eax,%eax                             #  ... which returns InstrField ptr
7025    jne     .LOP_IGET_CHAR_finish
7026    jmp     common_exceptionThrown
7027
7028.LOP_IGET_CHAR_finish:
7029    /*
7030     * Currently:
7031     *   eax holds resolved field
7032     *   ecx holds object
7033     *   rIBASE is scratch, but needs to be unspilled
7034     *   rINST_FULL holds A
7035     */
7036    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7037    UNSPILL(rIBASE)
7038    testl   %ecx,%ecx                            # object null?
7039    je      common_errNullObject                 # object was null
7040    movzwl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7041    movl    rINST_FULL,%eax                      # eax<- A
7042    FETCH_INST_WORD(2)
7043    SET_VREG(%ecx,%eax)
7044    ADVANCE_PC(2)
7045    GOTO_NEXT
7046
7047
7048/* continuation for OP_IGET_SHORT */
7049
7050
7051.LOP_IGET_SHORT_resolve:
7052    EXPORT_PC()
7053    SPILL(rPC)
7054    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7055    UNSPILL(rIBASE)
7056    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7057    SPILL_TMP(%ecx)                               # save object pointer across call
7058    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7059    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7060    UNSPILL_TMP(%ecx)
7061    UNSPILL(rPC)
7062    testl   %eax,%eax                             #  ... which returns InstrField ptr
7063    jne     .LOP_IGET_SHORT_finish
7064    jmp     common_exceptionThrown
7065
7066.LOP_IGET_SHORT_finish:
7067    /*
7068     * Currently:
7069     *   eax holds resolved field
7070     *   ecx holds object
7071     *   rIBASE is scratch, but needs to be unspilled
7072     *   rINST_FULL holds A
7073     */
7074    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7075    UNSPILL(rIBASE)
7076    testl   %ecx,%ecx                            # object null?
7077    je      common_errNullObject                 # object was null
7078    movswl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7079    movl    rINST_FULL,%eax                      # eax<- A
7080    FETCH_INST_WORD(2)
7081    SET_VREG(%ecx,%eax)
7082    ADVANCE_PC(2)
7083    GOTO_NEXT
7084
7085
7086/* continuation for OP_IPUT */
7087
7088
7089.LOP_IPUT_resolve:
7090    EXPORT_PC()
7091    SPILL(rPC)
7092    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7093    UNSPILL(rIBASE)
7094    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7095    SPILL_TMP(%ecx)                               # save object pointer across call
7096    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7097    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7098    UNSPILL_TMP(%ecx)
7099    UNSPILL(rPC)
7100    testl   %eax,%eax                             #  ... which returns InstrField ptr
7101    jne     .LOP_IPUT_finish
7102    jmp     common_exceptionThrown
7103
7104.LOP_IPUT_finish:
7105    /*
7106     * Currently:
7107     *   eax holds resolved field
7108     *   ecx holds object
7109     *   rIBASE is scratch, but needs to be unspilled
7110     *   rINST_FULL holds A
7111     */
7112    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7113    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7114    UNSPILL(rIBASE)
7115    testl   %ecx,%ecx                            # object null?
7116    je      common_errNullObject                 # object was null
7117    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7118    FETCH_INST_WORD(2)
7119    ADVANCE_PC(2)
7120    GOTO_NEXT
7121
7122/* continuation for OP_IPUT_WIDE */
7123
7124
7125.LOP_IPUT_WIDE_resolve:
7126    EXPORT_PC()
7127    SPILL(rPC)
7128    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7129    UNSPILL(rIBASE)
7130    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7131    SPILL_TMP(%ecx)                               # save object pointer across call
7132    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7133    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7134    UNSPILL_TMP(%ecx)
7135    UNSPILL(rPC)
7136    testl   %eax,%eax                             #  ... which returns InstrField ptr
7137    jne     .LOP_IPUT_WIDE_finish
7138    jmp     common_exceptionThrown
7139
7140.LOP_IPUT_WIDE_finish:
7141    /*
7142     * Currently:
7143     *   eax holds resolved field
7144     *   ecx holds object
7145     *   rIBASE is scratch, but needs to be unspilled
7146     *   rINST_FULL holds A
7147     */
7148    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7149    UNSPILL(rIBASE)
7150    testl   %ecx,%ecx                            # object null?
7151    je      common_errNullObject                 # object was null
7152    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
7153    GET_VREG_WORD(%ecx,rINST_FULL,0)             # ecx<- lsw
7154    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)       # rINST_FULL<- msw
7155    movl    rINST_FULL,4(%eax)
7156    FETCH_INST_WORD(2)
7157    movl    %ecx,(%eax)
7158    ADVANCE_PC(2)
7159    GOTO_NEXT
7160
7161/* continuation for OP_IPUT_OBJECT */
7162
7163
7164.LOP_IPUT_OBJECT_resolve:
7165    EXPORT_PC()
7166    SPILL(rPC)
7167    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7168    UNSPILL(rIBASE)
7169    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7170    SPILL_TMP(%ecx)                               # save object pointer across call
7171    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7172    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7173    UNSPILL_TMP(%ecx)
7174    UNSPILL(rPC)
7175    testl   %eax,%eax                             #  ... which returns InstrField ptr
7176    jne     .LOP_IPUT_OBJECT_finish
7177    jmp     common_exceptionThrown
7178
7179.LOP_IPUT_OBJECT_finish:
7180    /*
7181     * Currently:
7182     *   eax holds resolved field
7183     *   ecx holds object
7184     *   rIBASE is scratch, but needs to be unspilled
7185     *   rINST_FULL holds A
7186     */
7187    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7188    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7189    UNSPILL(rIBASE)
7190    testl   %ecx,%ecx                            # object null?
7191    je      common_errNullObject                 # object was null
7192    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7193    FETCH_INST_WORD(2)
7194    ADVANCE_PC(2)
7195    GOTO_NEXT
7196
7197/* continuation for OP_IPUT_BOOLEAN */
7198
7199
7200.LOP_IPUT_BOOLEAN_resolve:
7201    EXPORT_PC()
7202    SPILL(rPC)
7203    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7204    UNSPILL(rIBASE)
7205    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7206    SPILL_TMP(%ecx)                               # save object pointer across call
7207    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7208    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7209    UNSPILL_TMP(%ecx)
7210    UNSPILL(rPC)
7211    testl   %eax,%eax                             #  ... which returns InstrField ptr
7212    jne     .LOP_IPUT_BOOLEAN_finish
7213    jmp     common_exceptionThrown
7214
7215.LOP_IPUT_BOOLEAN_finish:
7216    /*
7217     * Currently:
7218     *   eax holds resolved field
7219     *   ecx holds object
7220     *   rIBASE is scratch, but needs to be unspilled
7221     *   rINST_FULL holds A
7222     */
7223    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7224    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7225    UNSPILL(rIBASE)
7226    testl   %ecx,%ecx                            # object null?
7227    je      common_errNullObject                 # object was null
7228    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7229    FETCH_INST_WORD(2)
7230    ADVANCE_PC(2)
7231    GOTO_NEXT
7232
7233/* continuation for OP_IPUT_BYTE */
7234
7235
7236.LOP_IPUT_BYTE_resolve:
7237    EXPORT_PC()
7238    SPILL(rPC)
7239    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7240    UNSPILL(rIBASE)
7241    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7242    SPILL_TMP(%ecx)                               # save object pointer across call
7243    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7244    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7245    UNSPILL_TMP(%ecx)
7246    UNSPILL(rPC)
7247    testl   %eax,%eax                             #  ... which returns InstrField ptr
7248    jne     .LOP_IPUT_BYTE_finish
7249    jmp     common_exceptionThrown
7250
7251.LOP_IPUT_BYTE_finish:
7252    /*
7253     * Currently:
7254     *   eax holds resolved field
7255     *   ecx holds object
7256     *   rIBASE is scratch, but needs to be unspilled
7257     *   rINST_FULL holds A
7258     */
7259    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7260    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7261    UNSPILL(rIBASE)
7262    testl   %ecx,%ecx                            # object null?
7263    je      common_errNullObject                 # object was null
7264    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7265    FETCH_INST_WORD(2)
7266    ADVANCE_PC(2)
7267    GOTO_NEXT
7268
7269/* continuation for OP_IPUT_CHAR */
7270
7271
7272.LOP_IPUT_CHAR_resolve:
7273    EXPORT_PC()
7274    SPILL(rPC)
7275    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7276    UNSPILL(rIBASE)
7277    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7278    SPILL_TMP(%ecx)                               # save object pointer across call
7279    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7280    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7281    UNSPILL_TMP(%ecx)
7282    UNSPILL(rPC)
7283    testl   %eax,%eax                             #  ... which returns InstrField ptr
7284    jne     .LOP_IPUT_CHAR_finish
7285    jmp     common_exceptionThrown
7286
7287.LOP_IPUT_CHAR_finish:
7288    /*
7289     * Currently:
7290     *   eax holds resolved field
7291     *   ecx holds object
7292     *   rIBASE is scratch, but needs to be unspilled
7293     *   rINST_FULL holds A
7294     */
7295    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7296    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7297    UNSPILL(rIBASE)
7298    testl   %ecx,%ecx                            # object null?
7299    je      common_errNullObject                 # object was null
7300    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7301    FETCH_INST_WORD(2)
7302    ADVANCE_PC(2)
7303    GOTO_NEXT
7304
7305/* continuation for OP_IPUT_SHORT */
7306
7307
7308.LOP_IPUT_SHORT_resolve:
7309    EXPORT_PC()
7310    SPILL(rPC)
7311    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7312    UNSPILL(rIBASE)
7313    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7314    SPILL_TMP(%ecx)                               # save object pointer across call
7315    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7316    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7317    UNSPILL_TMP(%ecx)
7318    UNSPILL(rPC)
7319    testl   %eax,%eax                             #  ... which returns InstrField ptr
7320    jne     .LOP_IPUT_SHORT_finish
7321    jmp     common_exceptionThrown
7322
7323.LOP_IPUT_SHORT_finish:
7324    /*
7325     * Currently:
7326     *   eax holds resolved field
7327     *   ecx holds object
7328     *   rIBASE is scratch, but needs to be unspilled
7329     *   rINST_FULL holds A
7330     */
7331    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7332    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7333    UNSPILL(rIBASE)
7334    testl   %ecx,%ecx                            # object null?
7335    je      common_errNullObject                 # object was null
7336    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7337    FETCH_INST_WORD(2)
7338    ADVANCE_PC(2)
7339    GOTO_NEXT
7340
7341/* continuation for OP_SGET */
7342
7343    /*
7344     * Go resolve the field
7345     */
7346.LOP_SGET_resolve:
7347    GET_GLUE(%ecx)
7348    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7349    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7350    EXPORT_PC()                                 # could throw, need to export
7351    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7352    SPILL(rPC)
7353    movl     %eax,OUT_ARG1(%esp)
7354    movl     %ecx,OUT_ARG0(%esp)
7355    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7356    UNSPILL(rPC)
7357    testl    %eax,%eax
7358    jne      .LOP_SGET_finish                 # success, continue
7359    jmp      common_exceptionThrown             # no, handle exception
7360
7361
7362/* continuation for OP_SGET_WIDE */
7363
7364    /*
7365     * Go resolve the field
7366     */
7367.LOP_SGET_WIDE_resolve:
7368    GET_GLUE(%ecx)
7369    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7370    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7371    EXPORT_PC()                                 # could throw, need to export
7372    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7373    SPILL(rPC)
7374    movl     %eax,OUT_ARG1(%esp)
7375    movl     %ecx,OUT_ARG0(%esp)
7376    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7377    UNSPILL(rPC)
7378    testl    %eax,%eax
7379    jne      .LOP_SGET_WIDE_finish                 # success, continue
7380    jmp      common_exceptionThrown             # no, handle exception
7381
7382
7383/* continuation for OP_SGET_OBJECT */
7384
7385    /*
7386     * Go resolve the field
7387     */
7388.LOP_SGET_OBJECT_resolve:
7389    GET_GLUE(%ecx)
7390    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7391    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7392    EXPORT_PC()                                 # could throw, need to export
7393    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7394    SPILL(rPC)
7395    movl     %eax,OUT_ARG1(%esp)
7396    movl     %ecx,OUT_ARG0(%esp)
7397    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7398    UNSPILL(rPC)
7399    testl    %eax,%eax
7400    jne      .LOP_SGET_OBJECT_finish                 # success, continue
7401    jmp      common_exceptionThrown             # no, handle exception
7402
7403
7404/* continuation for OP_SGET_BOOLEAN */
7405
7406    /*
7407     * Go resolve the field
7408     */
7409.LOP_SGET_BOOLEAN_resolve:
7410    GET_GLUE(%ecx)
7411    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7412    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7413    EXPORT_PC()                                 # could throw, need to export
7414    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7415    SPILL(rPC)
7416    movl     %eax,OUT_ARG1(%esp)
7417    movl     %ecx,OUT_ARG0(%esp)
7418    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7419    UNSPILL(rPC)
7420    testl    %eax,%eax
7421    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
7422    jmp      common_exceptionThrown             # no, handle exception
7423
7424
7425/* continuation for OP_SGET_BYTE */
7426
7427    /*
7428     * Go resolve the field
7429     */
7430.LOP_SGET_BYTE_resolve:
7431    GET_GLUE(%ecx)
7432    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7433    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7434    EXPORT_PC()                                 # could throw, need to export
7435    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7436    SPILL(rPC)
7437    movl     %eax,OUT_ARG1(%esp)
7438    movl     %ecx,OUT_ARG0(%esp)
7439    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7440    UNSPILL(rPC)
7441    testl    %eax,%eax
7442    jne      .LOP_SGET_BYTE_finish                 # success, continue
7443    jmp      common_exceptionThrown             # no, handle exception
7444
7445
7446/* continuation for OP_SGET_CHAR */
7447
7448    /*
7449     * Go resolve the field
7450     */
7451.LOP_SGET_CHAR_resolve:
7452    GET_GLUE(%ecx)
7453    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7454    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7455    EXPORT_PC()                                 # could throw, need to export
7456    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7457    SPILL(rPC)
7458    movl     %eax,OUT_ARG1(%esp)
7459    movl     %ecx,OUT_ARG0(%esp)
7460    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7461    UNSPILL(rPC)
7462    testl    %eax,%eax
7463    jne      .LOP_SGET_CHAR_finish                 # success, continue
7464    jmp      common_exceptionThrown             # no, handle exception
7465
7466
7467/* continuation for OP_SGET_SHORT */
7468
7469    /*
7470     * Go resolve the field
7471     */
7472.LOP_SGET_SHORT_resolve:
7473    GET_GLUE(%ecx)
7474    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7475    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7476    EXPORT_PC()                                 # could throw, need to export
7477    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7478    SPILL(rPC)
7479    movl     %eax,OUT_ARG1(%esp)
7480    movl     %ecx,OUT_ARG0(%esp)
7481    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7482    UNSPILL(rPC)
7483    testl    %eax,%eax
7484    jne      .LOP_SGET_SHORT_finish                 # success, continue
7485    jmp      common_exceptionThrown             # no, handle exception
7486
7487
7488/* continuation for OP_SPUT */
7489
7490    /*
7491     * Go resolve the field
7492     */
7493.LOP_SPUT_resolve:
7494    GET_GLUE(%ecx)
7495    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7496    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7497    EXPORT_PC()                                 # could throw, need to export
7498    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7499    SPILL(rPC)
7500    movl     %eax,OUT_ARG1(%esp)
7501    movl     %ecx,OUT_ARG0(%esp)
7502    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7503    UNSPILL(rPC)
7504    testl    %eax,%eax
7505    jne      .LOP_SPUT_finish                 # success, continue
7506    jmp      common_exceptionThrown             # no, handle exception
7507
7508
7509/* continuation for OP_SPUT_WIDE */
7510
7511    /*
7512     * Go resolve the field
7513     */
7514.LOP_SPUT_WIDE_resolve:
7515    GET_GLUE(%ecx)
7516    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7517    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7518    EXPORT_PC()                                 # could throw, need to export
7519    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7520    SPILL(rPC)
7521    movl     %eax,OUT_ARG1(%esp)
7522    movl     %ecx,OUT_ARG0(%esp)
7523    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7524    UNSPILL(rPC)
7525    testl    %eax,%eax
7526    jne      .LOP_SPUT_WIDE_finish                 # success, continue
7527    jmp      common_exceptionThrown             # no, handle exception
7528
7529
7530/* continuation for OP_SPUT_OBJECT */
7531
7532    /*
7533     * Go resolve the field
7534     */
7535.LOP_SPUT_OBJECT_resolve:
7536    GET_GLUE(%ecx)
7537    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7538    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7539    EXPORT_PC()                                 # could throw, need to export
7540    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7541    SPILL(rPC)
7542    movl     %eax,OUT_ARG1(%esp)
7543    movl     %ecx,OUT_ARG0(%esp)
7544    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7545    UNSPILL(rPC)
7546    testl    %eax,%eax
7547    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
7548    jmp      common_exceptionThrown             # no, handle exception
7549
7550
7551/* continuation for OP_SPUT_BOOLEAN */
7552
7553    /*
7554     * Go resolve the field
7555     */
7556.LOP_SPUT_BOOLEAN_resolve:
7557    GET_GLUE(%ecx)
7558    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7559    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7560    EXPORT_PC()                                 # could throw, need to export
7561    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7562    SPILL(rPC)
7563    movl     %eax,OUT_ARG1(%esp)
7564    movl     %ecx,OUT_ARG0(%esp)
7565    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7566    UNSPILL(rPC)
7567    testl    %eax,%eax
7568    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
7569    jmp      common_exceptionThrown             # no, handle exception
7570
7571
7572/* continuation for OP_SPUT_BYTE */
7573
7574    /*
7575     * Go resolve the field
7576     */
7577.LOP_SPUT_BYTE_resolve:
7578    GET_GLUE(%ecx)
7579    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7580    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7581    EXPORT_PC()                                 # could throw, need to export
7582    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7583    SPILL(rPC)
7584    movl     %eax,OUT_ARG1(%esp)
7585    movl     %ecx,OUT_ARG0(%esp)
7586    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7587    UNSPILL(rPC)
7588    testl    %eax,%eax
7589    jne      .LOP_SPUT_BYTE_finish                 # success, continue
7590    jmp      common_exceptionThrown             # no, handle exception
7591
7592
7593/* continuation for OP_SPUT_CHAR */
7594
7595    /*
7596     * Go resolve the field
7597     */
7598.LOP_SPUT_CHAR_resolve:
7599    GET_GLUE(%ecx)
7600    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7601    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7602    EXPORT_PC()                                 # could throw, need to export
7603    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7604    SPILL(rPC)
7605    movl     %eax,OUT_ARG1(%esp)
7606    movl     %ecx,OUT_ARG0(%esp)
7607    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7608    UNSPILL(rPC)
7609    testl    %eax,%eax
7610    jne      .LOP_SPUT_CHAR_finish                 # success, continue
7611    jmp      common_exceptionThrown             # no, handle exception
7612
7613
7614/* continuation for OP_SPUT_SHORT */
7615
7616    /*
7617     * Go resolve the field
7618     */
7619.LOP_SPUT_SHORT_resolve:
7620    GET_GLUE(%ecx)
7621    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7622    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7623    EXPORT_PC()                                 # could throw, need to export
7624    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7625    SPILL(rPC)
7626    movl     %eax,OUT_ARG1(%esp)
7627    movl     %ecx,OUT_ARG0(%esp)
7628    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7629    UNSPILL(rPC)
7630    testl    %eax,%eax
7631    jne      .LOP_SPUT_SHORT_finish                 # success, continue
7632    jmp      common_exceptionThrown             # no, handle exception
7633
7634
7635/* continuation for OP_INVOKE_VIRTUAL */
7636
7637
7638.LOP_INVOKE_VIRTUAL_more:
7639    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7640    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7641    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7642    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7643    UNSPILL(rPC)
7644    testl     %eax,%eax                   # got null?
7645    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
7646    jmp       common_exceptionThrown      # yes, handle exception
7647
7648    /* At this point:
7649     *   eax = resolved base method
7650     *   ecx = scratch
7651     */
7652.LOP_INVOKE_VIRTUAL_continue:
7653    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7654    .if       (!0)
7655    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7656    .endif
7657    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7658    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7659    testl     %ecx,%ecx                 # null this?
7660    je        common_errNullObject      # go if so
7661    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7662    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7663    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7664    movl      $0,%ecx           # needed for common_invokeOld
7665    #jmp       common_invokeMethodNoRange
7666    jmp       common_invokeOld
7667
7668
7669/* continuation for OP_INVOKE_SUPER */
7670
7671    /*
7672     * At this point:
7673     *  ecx = resolved base method [r0]
7674     *  eax = method->clazz [r9]
7675     */
7676.LOP_INVOKE_SUPER_continue:
7677    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7678    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7679    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7680    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
7681    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7682    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7683    movl    $0,%ecx
7684    #jmp     common_invokeMethodNoRange
7685    jmp     common_invokeOld
7686
7687    /* At this point:
7688     * ecx = null (needs to be resolved base method)
7689     * eax = method->clazz
7690    */
7691.LOP_INVOKE_SUPER_resolve:
7692    SPILL_TMP(%eax)                     # method->clazz
7693    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7694    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7695    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7696    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7697    SPILL(rPC)
7698    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7699    UNSPILL(rPC)
7700    testl   %eax,%eax                   # got null?
7701    movl    %eax,%ecx                   # ecx<- resolved base method
7702    UNSPILL_TMP(%eax)                   # restore method->clazz
7703    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
7704    jmp     common_exceptionThrown      # handle exception
7705
7706    /*
7707     * Throw a NoSuchMethodError with the method name as the message.
7708     *  ecx = resolved base method
7709     */
7710.LOP_INVOKE_SUPER_nsm:
7711    movl    offMethod_name(%ecx),%eax
7712    mov     %eax,OUT_ARG1(%esp)
7713    jmp     common_errNoSuchMethod
7714
7715/* continuation for OP_INVOKE_DIRECT */
7716
7717    /*
7718     * On entry:
7719     *   TMP_SPILL  <- "this" register
7720     * Things a bit ugly on this path, but it's the less
7721     * frequent one.  We'll have to do some reloading.
7722     */
7723.LOP_INVOKE_DIRECT_resolve:
7724     SPILL_TMP(%ecx)
7725     GET_GLUE(%ecx)
7726     UNSPILL(rPC)
7727     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7728     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7729     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7730     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7731     movl     %eax,OUT_ARG1(%esp)
7732     movl     %ecx,OUT_ARG0(%esp)
7733     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7734     UNSPILL_TMP(%ecx)
7735     testl    %eax,%eax
7736     jne      .LOP_INVOKE_DIRECT_finish
7737     UNSPILL(rPC)
7738     jmp      common_exceptionThrown
7739
7740/* continuation for OP_INVOKE_STATIC */
7741
7742.LOP_INVOKE_STATIC_continue:
7743    movl      $METHOD_STATIC,%eax
7744    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7745    SPILL(rPC)
7746    call      dvmResolveMethod          # call(clazz,ref,flags)
7747    UNSPILL(rPC)
7748    movl      $0,%ecx
7749    testl     %eax,%eax                 # got null?
7750    #jne       common_invokeMethodNoRange
7751    jne       common_invokeOld
7752    jmp       common_exceptionThrown
7753
7754
7755/* continuation for OP_INVOKE_INTERFACE */
7756
7757.LOP_INVOKE_INTERFACE_continue:
7758    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7759    UNSPILL(rPC)
7760    testl      %eax,%eax
7761    je         common_exceptionThrown
7762    movl       $0,%ecx
7763    #jmp        common_invokeMethodNoRange
7764    jmp        common_invokeOld
7765
7766
7767/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7768
7769
7770.LOP_INVOKE_VIRTUAL_RANGE_more:
7771    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7772    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7773    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7774    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7775    UNSPILL(rPC)
7776    testl     %eax,%eax                   # got null?
7777    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
7778    jmp       common_exceptionThrown      # yes, handle exception
7779
7780    /* At this point:
7781     *   eax = resolved base method
7782     *   ecx = scratch
7783     */
7784.LOP_INVOKE_VIRTUAL_RANGE_continue:
7785    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7786    .if       (!1)
7787    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7788    .endif
7789    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7790    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7791    testl     %ecx,%ecx                 # null this?
7792    je        common_errNullObject      # go if so
7793    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7794    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7795    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7796    movl      $1,%ecx           # needed for common_invokeOld
7797    #jmp       common_invokeMethodRange
7798    jmp       common_invokeOld
7799
7800
7801/* continuation for OP_INVOKE_SUPER_RANGE */
7802
7803    /*
7804     * At this point:
7805     *  ecx = resolved base method [r0]
7806     *  eax = method->clazz [r9]
7807     */
7808.LOP_INVOKE_SUPER_RANGE_continue:
7809    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7810    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7811    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7812    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
7813    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7814    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7815    movl    $1,%ecx
7816    #jmp     common_invokeMethodRange
7817    jmp     common_invokeOld
7818
7819    /* At this point:
7820     * ecx = null (needs to be resolved base method)
7821     * eax = method->clazz
7822    */
7823.LOP_INVOKE_SUPER_RANGE_resolve:
7824    SPILL_TMP(%eax)                     # method->clazz
7825    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7826    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7827    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7828    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7829    SPILL(rPC)
7830    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7831    UNSPILL(rPC)
7832    testl   %eax,%eax                   # got null?
7833    movl    %eax,%ecx                   # ecx<- resolved base method
7834    UNSPILL_TMP(%eax)                   # restore method->clazz
7835    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
7836    jmp     common_exceptionThrown      # handle exception
7837
7838    /*
7839     * Throw a NoSuchMethodError with the method name as the message.
7840     *  ecx = resolved base method
7841     */
7842.LOP_INVOKE_SUPER_RANGE_nsm:
7843    movl    offMethod_name(%ecx),%eax
7844    mov     %eax,OUT_ARG1(%esp)
7845    jmp     common_errNoSuchMethod
7846
7847/* continuation for OP_INVOKE_DIRECT_RANGE */
7848
7849    /*
7850     * On entry:
7851     *   TMP_SPILL  <- "this" register
7852     * Things a bit ugly on this path, but it's the less
7853     * frequent one.  We'll have to do some reloading.
7854     */
7855.LOP_INVOKE_DIRECT_RANGE_resolve:
7856     SPILL_TMP(%ecx)
7857     GET_GLUE(%ecx)
7858     UNSPILL(rPC)
7859     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7860     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7861     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7862     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7863     movl     %eax,OUT_ARG1(%esp)
7864     movl     %ecx,OUT_ARG0(%esp)
7865     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7866     UNSPILL_TMP(%ecx)
7867     testl    %eax,%eax
7868     jne      .LOP_INVOKE_DIRECT_RANGE_finish
7869     UNSPILL(rPC)
7870     jmp      common_exceptionThrown
7871
7872/* continuation for OP_INVOKE_STATIC_RANGE */
7873
7874.LOP_INVOKE_STATIC_RANGE_continue:
7875    movl      $METHOD_STATIC,%eax
7876    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7877    SPILL(rPC)
7878    call      dvmResolveMethod          # call(clazz,ref,flags)
7879    UNSPILL(rPC)
7880    movl      $1,%ecx
7881    testl     %eax,%eax                 # got null?
7882    #jne       common_invokeMethodRange
7883    jne       common_invokeOld
7884    jmp       common_exceptionThrown
7885
7886
7887/* continuation for OP_INVOKE_INTERFACE_RANGE */
7888
7889.LOP_INVOKE_INTERFACE_RANGE_continue:
7890    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7891    UNSPILL(rPC)
7892    testl      %eax,%eax
7893    je         common_exceptionThrown
7894    movl       $1,%ecx
7895    #jmp        common_invokeMethodRange
7896    jmp        common_invokeOld
7897
7898
7899/* continuation for OP_FLOAT_TO_INT */
7900
7901
7902.LOP_FLOAT_TO_INT_continue:
7903    .if 0
7904    movl     $0x80000000,%eax
7905    xorl     4(rFP,%ecx,4),%eax
7906    orl      (rFP,%ecx,4),%eax
7907    .else
7908    cmpl     $0x80000000,(rFP,%ecx,4)
7909    .endif
7910    je       .LOP_FLOAT_TO_INT_special_case # fix up result
7911
7912.LOP_FLOAT_TO_INT_finish:
7913    ADVANCE_PC(1)
7914    GOTO_NEXT
7915
7916.LOP_FLOAT_TO_INT_special_case:
7917    fnstsw   %ax
7918    sahf
7919    jp       .LOP_FLOAT_TO_INT_isNaN
7920    adcl     $-1,(rFP,%ecx,4)
7921    .if 0
7922    adcl     $-1,4(rFP,%ecx,4)
7923    .endif
7924   jmp       .LOP_FLOAT_TO_INT_finish
7925.LOP_FLOAT_TO_INT_isNaN:
7926    movl      $0,(rFP,%ecx,4)
7927    .if 0
7928    movl      $0,4(rFP,%ecx,4)
7929    .endif
7930    jmp       .LOP_FLOAT_TO_INT_finish
7931
7932/* continuation for OP_FLOAT_TO_LONG */
7933
7934
7935.LOP_FLOAT_TO_LONG_continue:
7936    .if 1
7937    movl     $0x80000000,%eax
7938    xorl     4(rFP,%ecx,4),%eax
7939    orl      (rFP,%ecx,4),%eax
7940    .else
7941    cmpl     $0x80000000,(rFP,%ecx,4)
7942    .endif
7943    je       .LOP_FLOAT_TO_LONG_special_case # fix up result
7944
7945.LOP_FLOAT_TO_LONG_finish:
7946    ADVANCE_PC(1)
7947    GOTO_NEXT
7948
7949.LOP_FLOAT_TO_LONG_special_case:
7950    fnstsw   %ax
7951    sahf
7952    jp       .LOP_FLOAT_TO_LONG_isNaN
7953    adcl     $-1,(rFP,%ecx,4)
7954    .if 1
7955    adcl     $-1,4(rFP,%ecx,4)
7956    .endif
7957   jmp       .LOP_FLOAT_TO_LONG_finish
7958.LOP_FLOAT_TO_LONG_isNaN:
7959    movl      $0,(rFP,%ecx,4)
7960    .if 1
7961    movl      $0,4(rFP,%ecx,4)
7962    .endif
7963    jmp       .LOP_FLOAT_TO_LONG_finish
7964
7965/* continuation for OP_DOUBLE_TO_INT */
7966
7967
7968.LOP_DOUBLE_TO_INT_continue:
7969    .if 0
7970    movl     $0x80000000,%eax
7971    xorl     4(rFP,%ecx,4),%eax
7972    orl      (rFP,%ecx,4),%eax
7973    .else
7974    cmpl     $0x80000000,(rFP,%ecx,4)
7975    .endif
7976    je       .LOP_DOUBLE_TO_INT_special_case # fix up result
7977
7978.LOP_DOUBLE_TO_INT_finish:
7979    ADVANCE_PC(1)
7980    GOTO_NEXT
7981
7982.LOP_DOUBLE_TO_INT_special_case:
7983    fnstsw   %ax
7984    sahf
7985    jp       .LOP_DOUBLE_TO_INT_isNaN
7986    adcl     $-1,(rFP,%ecx,4)
7987    .if 0
7988    adcl     $-1,4(rFP,%ecx,4)
7989    .endif
7990   jmp       .LOP_DOUBLE_TO_INT_finish
7991.LOP_DOUBLE_TO_INT_isNaN:
7992    movl      $0,(rFP,%ecx,4)
7993    .if 0
7994    movl      $0,4(rFP,%ecx,4)
7995    .endif
7996    jmp       .LOP_DOUBLE_TO_INT_finish
7997
7998/* continuation for OP_DOUBLE_TO_LONG */
7999
8000
8001.LOP_DOUBLE_TO_LONG_continue:
8002    .if 1
8003    movl     $0x80000000,%eax
8004    xorl     4(rFP,%ecx,4),%eax
8005    orl      (rFP,%ecx,4),%eax
8006    .else
8007    cmpl     $0x80000000,(rFP,%ecx,4)
8008    .endif
8009    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result
8010
8011.LOP_DOUBLE_TO_LONG_finish:
8012    ADVANCE_PC(1)
8013    GOTO_NEXT
8014
8015.LOP_DOUBLE_TO_LONG_special_case:
8016    fnstsw   %ax
8017    sahf
8018    jp       .LOP_DOUBLE_TO_LONG_isNaN
8019    adcl     $-1,(rFP,%ecx,4)
8020    .if 1
8021    adcl     $-1,4(rFP,%ecx,4)
8022    .endif
8023   jmp       .LOP_DOUBLE_TO_LONG_finish
8024.LOP_DOUBLE_TO_LONG_isNaN:
8025    movl      $0,(rFP,%ecx,4)
8026    .if 1
8027    movl      $0,4(rFP,%ecx,4)
8028    .endif
8029    jmp       .LOP_DOUBLE_TO_LONG_finish
8030
8031/* continuation for OP_DIV_INT */
8032.LOP_DIV_INT_continue_div:
8033    cltd
8034    idivl   %ecx
8035.LOP_DIV_INT_finish_div:
8036    movzbl   rINST_HI,%ecx         # ecl<- AA
8037    SET_VREG(%eax,%ecx)
8038    UNSPILL(rPC)
8039    FETCH_INST_WORD(2)
8040    ADVANCE_PC(2)
8041    GOTO_NEXT
8042
8043/* continuation for OP_REM_INT */
8044.LOP_REM_INT_continue_div:
8045    cltd
8046    idivl   %ecx
8047.LOP_REM_INT_finish_div:
8048    movzbl   rINST_HI,%ecx         # ecl<- AA
8049    SET_VREG(%edx,%ecx)
8050    UNSPILL(rPC)
8051    FETCH_INST_WORD(2)
8052    ADVANCE_PC(2)
8053    GOTO_NEXT
8054
8055/* continuation for OP_MUL_LONG */
8056
8057.LOP_MUL_LONG_continue:
8058    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8059    movzbl    rINST_HI,%ecx       # ecx<- A
8060    movl      %edx,4(rFP,%ecx,4)  # v[B+1]<- %edx
8061    UNSPILL(rPC)                  # restore rPC/%edx
8062    FETCH_INST_WORD(2)
8063    UNSPILL(rIBASE)
8064    movl      %eax,(rFP,%ecx,4)   # v[B]<- %eax
8065    ADVANCE_PC(2)
8066    GOTO_NEXT
8067
8068
8069/* continuation for OP_DIV_LONG */
8070
8071.LOP_DIV_LONG_continue:
8072    call     __divdi3
8073.LOP_DIV_LONG_finish:
8074    movzbl   rINST_HI,%ecx
8075    SET_VREG_WORD(rPC,%ecx,1)
8076    UNSPILL(rPC)
8077    SET_VREG_WORD(%eax,%ecx,0)
8078    FETCH_INST_WORD(2)
8079    ADVANCE_PC(2)
8080    GOTO_NEXT
8081
8082.LOP_DIV_LONG_check_zero:
8083    testl   rPC,rPC
8084    jne     .LOP_DIV_LONG_notSpecial
8085    UNSPILL(rPC)
8086    jmp     common_errDivideByZero
8087.LOP_DIV_LONG_check_neg1:
8088    testl   rPC,%eax
8089    jne     .LOP_DIV_LONG_notSpecial
8090    GET_VREG_WORD(rPC,%ecx,0)
8091    GET_VREG_WORD(%ecx,%ecx,1)
8092    testl    rPC,rPC
8093    jne      .LOP_DIV_LONG_notSpecial1
8094    cmpl     $0x80000000,%ecx
8095    jne      .LOP_DIV_LONG_notSpecial1
8096    /* minint / -1, return minint on div, 0 on rem */
8097    xorl     %eax,%eax
8098    movl     $0x80000000,%edx
8099    jmp      .LOP_DIV_LONG_finish
8100
8101
8102
8103
8104/* continuation for OP_REM_LONG */
8105
8106.LOP_REM_LONG_continue:
8107    call     __moddi3
8108.LOP_REM_LONG_finish:
8109    movzbl   rINST_HI,%ecx
8110    SET_VREG_WORD(rPC,%ecx,1)
8111    UNSPILL(rPC)
8112    SET_VREG_WORD(%eax,%ecx,0)
8113    FETCH_INST_WORD(2)
8114    ADVANCE_PC(2)
8115    GOTO_NEXT
8116
8117.LOP_REM_LONG_check_zero:
8118    testl   rPC,rPC
8119    jne     .LOP_REM_LONG_notSpecial
8120    UNSPILL(rPC)
8121    jmp     common_errDivideByZero
8122.LOP_REM_LONG_check_neg1:
8123    testl   rPC,%eax
8124    jne     .LOP_REM_LONG_notSpecial
8125    GET_VREG_WORD(rPC,%ecx,0)
8126    GET_VREG_WORD(%ecx,%ecx,1)
8127    testl    rPC,rPC
8128    jne      .LOP_REM_LONG_notSpecial1
8129    cmpl     $0x80000000,%ecx
8130    jne      .LOP_REM_LONG_notSpecial1
8131    /* minint / -1, return minint on div, 0 on rem */
8132    xorl     %eax,%eax
8133    movl     $0,%edx
8134    jmp      .LOP_REM_LONG_finish
8135
8136
8137
8138
8139/* continuation for OP_SHL_LONG */
8140
8141.LOP_SHL_LONG_finish:
8142    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- %eax
8143    ADVANCE_PC(2)
8144    GOTO_NEXT
8145
8146/* continuation for OP_SHR_LONG */
8147
8148
8149.LOP_SHR_LONG_finish:
8150    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- eax
8151    ADVANCE_PC(2)
8152    GOTO_NEXT
8153
8154/* continuation for OP_USHR_LONG */
8155
8156
8157.LOP_USHR_LONG_finish:
8158    SET_VREG_WORD(%eax,%ecx,0)        # v[BB+0]<- eax
8159    FETCH_INST_WORD(2)
8160    ADVANCE_PC(2)
8161    GOTO_NEXT
8162
8163/* continuation for OP_DIV_INT_2ADDR */
8164.LOP_DIV_INT_2ADDR_continue_div2addr:
8165    cltd
8166    idivl   %ecx
8167.LOP_DIV_INT_2ADDR_finish_div2addr:
8168    SET_VREG(%eax,rINST_FULL)
8169    UNSPILL(rPC)
8170    FETCH_INST_WORD(1)
8171    ADVANCE_PC(1)
8172    GOTO_NEXT
8173
8174/* continuation for OP_REM_INT_2ADDR */
8175.LOP_REM_INT_2ADDR_continue_div2addr:
8176    cltd
8177    idivl   %ecx
8178.LOP_REM_INT_2ADDR_finish_div2addr:
8179    SET_VREG(%edx,rINST_FULL)
8180    UNSPILL(rPC)
8181    FETCH_INST_WORD(1)
8182    ADVANCE_PC(1)
8183    GOTO_NEXT
8184
8185/* continuation for OP_MUL_LONG_2ADDR */
8186
8187.LOP_MUL_LONG_2ADDR_continue:
8188    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8189    movl      %edx,4(rIBASE)      # v[A+1]<- %edx
8190    UNSPILL(rPC)                  # restore rPC/%edx
8191    FETCH_INST_WORD(1)
8192    movl      %eax,(rIBASE)       # v[A]<- %eax
8193    UNSPILL(rFP)
8194    UNSPILL(rIBASE)
8195    ADVANCE_PC(1)
8196    GOTO_NEXT
8197
8198
8199/* continuation for OP_DIV_LONG_2ADDR */
8200
8201.LOP_DIV_LONG_2ADDR_continue:
8202    movl     %eax,OUT_ARG3(%esp)
8203    movl     rPC,OUT_ARG0(%esp)
8204    movl     %ecx,OUT_ARG1(%esp)
8205    call     __divdi3
8206.LOP_DIV_LONG_2ADDR_finish:
8207    movl     rINST_FULL,%ecx
8208    SET_VREG_WORD(rPC,%ecx,1)
8209    UNSPILL(rPC)
8210    SET_VREG_WORD(%eax,%ecx,0)
8211    FETCH_INST_WORD(1)
8212    ADVANCE_PC(1)
8213    GOTO_NEXT
8214
8215.LOP_DIV_LONG_2ADDR_check_zero:
8216    testl   rPC,rPC
8217    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8218    UNSPILL(rPC)
8219    jmp     common_errDivideByZero
8220.LOP_DIV_LONG_2ADDR_check_neg1:
8221    testl   rPC,%eax
8222    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8223    GET_VREG_WORD(rPC,rINST_FULL,0)
8224    GET_VREG_WORD(%ecx,rINST_FULL,1)
8225    testl    rPC,rPC
8226    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8227    cmpl     $0x80000000,%ecx
8228    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8229    /* minint / -1, return minint on div, 0 on rem */
8230    xorl     %eax,%eax
8231    movl     $0x80000000,%edx
8232    jmp      .LOP_DIV_LONG_2ADDR_finish
8233
8234
8235/* continuation for OP_REM_LONG_2ADDR */
8236
8237.LOP_REM_LONG_2ADDR_continue:
8238    movl     %eax,OUT_ARG3(%esp)
8239    movl     rPC,OUT_ARG0(%esp)
8240    movl     %ecx,OUT_ARG1(%esp)
8241    call     __moddi3
8242.LOP_REM_LONG_2ADDR_finish:
8243    movl     rINST_FULL,%ecx
8244    SET_VREG_WORD(rPC,%ecx,1)
8245    UNSPILL(rPC)
8246    SET_VREG_WORD(%eax,%ecx,0)
8247    FETCH_INST_WORD(1)
8248    ADVANCE_PC(1)
8249    GOTO_NEXT
8250
8251.LOP_REM_LONG_2ADDR_check_zero:
8252    testl   rPC,rPC
8253    jne     .LOP_REM_LONG_2ADDR_notSpecial
8254    UNSPILL(rPC)
8255    jmp     common_errDivideByZero
8256.LOP_REM_LONG_2ADDR_check_neg1:
8257    testl   rPC,%eax
8258    jne     .LOP_REM_LONG_2ADDR_notSpecial
8259    GET_VREG_WORD(rPC,rINST_FULL,0)
8260    GET_VREG_WORD(%ecx,rINST_FULL,1)
8261    testl    rPC,rPC
8262    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8263    cmpl     $0x80000000,%ecx
8264    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8265    /* minint / -1, return minint on div, 0 on rem */
8266    xorl     %eax,%eax
8267    movl     $0,%edx
8268    jmp      .LOP_REM_LONG_2ADDR_finish
8269
8270
8271/* continuation for OP_SHL_LONG_2ADDR */
8272
8273
8274.LOP_SHL_LONG_2ADDR_finish:
8275    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8276    FETCH_INST_WORD(1)
8277    ADVANCE_PC(1)
8278    GOTO_NEXT
8279
8280/* continuation for OP_SHR_LONG_2ADDR */
8281
8282
8283.LOP_SHR_LONG_2ADDR_finish:
8284    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8285    FETCH_INST_WORD(1)
8286    ADVANCE_PC(1)
8287    GOTO_NEXT
8288
8289/* continuation for OP_USHR_LONG_2ADDR */
8290
8291
8292.LOP_USHR_LONG_2ADDR_finish:
8293    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[AA+0]<- eax
8294    FETCH_INST_WORD(1)
8295    ADVANCE_PC(1)
8296    GOTO_NEXT
8297
8298/* continuation for OP_DIV_INT_LIT16 */
8299.LOP_DIV_INT_LIT16_continue_div:
8300    cltd
8301    idivl   %ecx
8302.LOP_DIV_INT_LIT16_finish_div:
8303    SET_VREG(%eax,rINST_FULL)
8304    UNSPILL(rPC)
8305    FETCH_INST_WORD(2)
8306    ADVANCE_PC(2)
8307    GOTO_NEXT
8308
8309/* continuation for OP_REM_INT_LIT16 */
8310.LOP_REM_INT_LIT16_continue_div:
8311    cltd
8312    idivl   %ecx
8313.LOP_REM_INT_LIT16_finish_div:
8314    SET_VREG(%edx,rINST_FULL)
8315    UNSPILL(rPC)
8316    FETCH_INST_WORD(2)
8317    ADVANCE_PC(2)
8318    GOTO_NEXT
8319
8320/* continuation for OP_DIV_INT_LIT8 */
8321.LOP_DIV_INT_LIT8_continue_div:
8322    cltd
8323    idivl   %ecx
8324.LOP_DIV_INT_LIT8_finish_div:
8325    SET_VREG(%eax,rINST_FULL)
8326    UNSPILL(rPC)
8327    FETCH_INST_WORD(2)
8328    ADVANCE_PC(2)
8329    GOTO_NEXT
8330
8331/* continuation for OP_REM_INT_LIT8 */
8332.LOP_REM_INT_LIT8_continue_div:
8333    cltd
8334    idivl   %ecx
8335.LOP_REM_INT_LIT8_finish_div:
8336    SET_VREG(%edx,rINST_FULL)
8337    UNSPILL(rPC)
8338    FETCH_INST_WORD(2)
8339    ADVANCE_PC(2)
8340    GOTO_NEXT
8341
8342/* continuation for OP_EXECUTE_INLINE */
8343
8344.LOP_EXECUTE_INLINE_continue:
8345    /*
8346     * Extract args, call function.
8347     *  ecx = #of args (0-4)
8348     *  eax = call index
8349     *  @esp = return addr
8350     *  esp is -4 from normal
8351     *
8352     *  Go ahead and load all 4 args, even if not used.
8353     */
8354    movzwl    4(rPC),rPC
8355
8356    movl      $0xf,%ecx
8357    andl      rPC,%ecx
8358    GET_VREG(%ecx,%ecx)
8359    sarl      $4,rPC
8360    movl      %ecx,4+OUT_ARG0(%esp)
8361
8362    movl      $0xf,%ecx
8363    andl      rPC,%ecx
8364    GET_VREG(%ecx,%ecx)
8365    sarl      $4,rPC
8366    movl      %ecx,4+OUT_ARG1(%esp)
8367
8368    movl      $0xf,%ecx
8369    andl      rPC,%ecx
8370    GET_VREG(%ecx,%ecx)
8371    sarl      $4,rPC
8372    movl      %ecx,4+OUT_ARG2(%esp)
8373
8374    movl      $0xf,%ecx
8375    andl      rPC,%ecx
8376    GET_VREG(%ecx,%ecx)
8377    sarl      $4,rPC
8378    movl      %ecx,4+OUT_ARG3(%esp)
8379
8380    sall      $4,%eax      # index *= sizeof(table entry)
8381    jmp       *gDvmInlineOpsTable(%eax)
8382    # will return to caller of .LOP_EXECUTE_INLINE_continue
8383
8384
8385    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8386    .global dvmAsmSisterEnd
8387dvmAsmSisterEnd:
8388
8389/* File: x86/entry.S */
8390/*
8391 * Copyright (C) 2008 The Android Open Source Project
8392 *
8393 * Licensed under the Apache License, Version 2.0 (the "License");
8394 * you may not use this file except in compliance with the License.
8395 * You may obtain a copy of the License at
8396 *
8397 *      http://www.apache.org/licenses/LICENSE-2.0
8398 *
8399 * Unless required by applicable law or agreed to in writing, software
8400 * distributed under the License is distributed on an "AS IS" BASIS,
8401 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8402 * See the License for the specific language governing permissions and
8403 * limitations under the License.
8404 */
8405
8406
8407    .text
8408    .global dvmMterpStdRun
8409    .type   dvmMterpStdRun, %function
8410/*
8411 * bool dvmMterpStdRun(MterpGlue* glue)
8412 *
8413 * Interpreter entry point.  Returns changeInterp.
8414 *
8415 */
8416dvmMterpStdRun:
8417    push    %ebp
8418    movl    %esp,%ebp
8419    push    %edi
8420    push    %esi
8421    push    %ebx
8422
8423/* at this point, stack is misaligned by 1 word
8424   We're allocating spill space for 6 words, plus
8425   outgoing argument (5 words) and local variables
8426   (4 words) - 15 words or 60 bytes total. See
8427   diagram in header.S
8428*/
8429    subl   $60,%esp
8430
8431/* Set up "named" registers */
8432    movl    IN_ARG0(%ebp),%ecx
8433    movl    %ecx,rGLUE_SPILL(%ebp)
8434    LOAD_PC_FROM_GLUE(%ecx)
8435    LOAD_FP_FROM_GLUE(%ecx)
8436    movl    $dvmAsmInstructionStart,rIBASE
8437
8438/* Remember %esp for future "longjmp" */
8439    movl    %esp,offGlue_bailPtr(%ecx)
8440
8441/* How to start? */
8442    movb    offGlue_entryPoint(%ecx),%al
8443
8444/* Normal start? */
8445    cmpb    $kInterpEntryInstr,%al
8446    jne     .Lnot_instr
8447
8448   /* Normal case: start executing the instruction at rPC */
8449    FETCH_INST()
8450    GOTO_NEXT
8451
8452.Lnot_instr:
8453    /* Reset to normal case */
8454    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8455    cmpb   $kInterpEntryReturn,%al
8456    je     common_returnFromMethod
8457    cmpb   $kInterpEntryThrow,%al
8458    je     common_exceptionThrown
8459    movzx  %al,%eax
8460    movl   %eax,OUT_ARG1(%esp)
8461    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
8462    call   printf
8463    call   dvmAbort
8464    /* Not reached */
8465
8466
8467    .global dvmMterpStdBail
8468    .type   dvmMterpStdBail, %function
8469/*
8470 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8471 *
8472 * Restore the stack pointer and PC from the save point established on entry.
8473 * This is essentially the same as a longjmp, but should be cheaper.  The
8474 * last instruction causes us to return to whoever called dvmMterpStdRun.
8475 *
8476 * We're not going to build a standard frame here, so the arg accesses will
8477 * look a little strange.
8478 *
8479 * On entry:
8480 *  esp+4 (arg0)  MterpGlue* glue
8481 *  esp+8 (arg1)  bool changeInterp
8482 */
8483dvmMterpStdBail:
8484    movl    4(%esp),%ecx                 # grab glue
8485    movl    8(%esp),%eax                 # changeInterp to return reg
8486    movl    offGlue_bailPtr(%ecx),%esp   # Stack back to normal
8487    addl    $60,%esp                    # Strip dvmMterpStdRun's frame
8488    pop     %ebx
8489    pop     %esi
8490    pop     %edi
8491    pop     %ebp
8492    ret                                  # return to dvmMterpStdRun's caller
8493
8494
8495/*
8496 * Strings
8497 */
8498    .section    .rodata
8499.LstrBadEntryPoint:
8500    .asciz  "Bad entry point %d\n"
8501
8502/* File: x86/footer.S */
8503/*
8504 * Copyright (C) 2008 The Android Open Source Project
8505 *
8506 * Licensed under the Apache License, Version 2.0 (the "License");
8507 * you may not use this file except in compliance with the License.
8508 * You may obtain a copy of the License at
8509 *
8510 *      http://www.apache.org/licenses/LICENSE-2.0
8511 *
8512 * Unless required by applicable law or agreed to in writing, software
8513 * distributed under the License is distributed on an "AS IS" BASIS,
8514 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8515 * See the License for the specific language governing permissions and
8516 * limitations under the License.
8517 */
8518/*
8519 * Common subroutines and data.
8520 */
8521
8522/*
8523 * Common code when a backwards branch is taken
8524 *
8525 * On entry:
8526 *   ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
8527 */
8528common_backwardBranch:
8529    GET_GLUE(%ecx)
8530    call   common_periodicChecks      # Note: expects rPC to be preserved
8531    ADVANCE_PC_INDEXED(rINST_FULL)
8532    FETCH_INST()
8533    GOTO_NEXT
8534
8535/*
8536 * Common invoke code (old-style).
8537 * TUNING:  Rewrite along lines of new armv5 code?
8538 *
8539 * On entry:
8540 *   eax = Method* methodToCall
8541 *   ecx = bool methodCallRange
8542 *   rINST trashed, must reload
8543 */
8544common_invokeOld:
8545    movl     %ecx,OUT_ARG1(%esp)     # arg1<- methodCallRange
8546    GET_GLUE(%ecx)
8547    movzwl  (rPC),rINST_FULL         # recover rINST
8548    movl     %eax,OUT_ARG2(%esp)     # arg2<- method
8549    movzwl   4(rPC),%eax             # eax<- GFED or CCCC
8550    SAVE_PC_TO_GLUE(%ecx)
8551    SAVE_FP_TO_GLUE(%ecx)
8552    movzbl   rINST_HI,rINST_FULL
8553    movl     rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
8554    movl     %ecx,OUT_ARG0(%esp)     # arg0<- GLUE
8555    movl     %eax,OUT_ARG4(%esp)     # arg4<- GFED/CCCC
8556    call     dvmMterp_invokeMethod
8557    jmp      common_resumeAfterGlueCall
8558
8559
8560/*
8561 * Do we need the thread to be suspended or have debugger/profiling activity?
8562 *
8563 * On entry:
8564 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
8565 *   ecx  -> GLUE pointer
8566 *
8567 * Note: A call will normally kill %eax, rPC/%edx and %ecx.  To
8568 *       streamline the normal case, this routine will preserve rPC and
8569 *       %ecx in addition to the normal caller save regs.  The save/restore
8570 *       is a bit ugly, but will happen in the relatively uncommon path.
8571 * TUNING: Might be worthwhile to inline this.
8572 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
8573 *       the suspendCount check so we can get both in 1 shot.
8574 */
8575common_periodicChecks:
8576    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
8577    cmpl    $0,(%eax)
8578    jne     1f
8579
8580#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
8581#if defined(WITH_DEBUGGER)
8582    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
8583#endif
8584#if defined(WITH_PROFILER)
8585    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
8586#endif
8587#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
8588    movzbl (%eax),%eax             # eax <- debuggerActive (boolean)
8589    orl    (%ecx),%eax             # eax <- debuggerActive || activeProfilers
8590#elif defined(WITH_DEBUGGER)
8591    movzbl (%eax),%eax             # eax <- debuggerActive (boolean)
8592#elif defined(WITH_PROFILER)
8593    movl   (%ecx),%eax             # eax <= activeProfilers
8594#endif
8595    GET_GLUE(%ecx)                 # restore rGLUE
8596    testl  %eax,%eax
8597    jne    3f                      # one or both active - switch interp
8598#endif
8599
8600    ret
8601
8602    /* Check for suspend */
86031:
8604    /*  At this point, the return pointer to the caller of
8605     *  common_periodicChecks is on the top of stack.  We need to preserve
8606     *  rPC(edx) and GLUE(ecx).  We'll spill rPC, and reload GLUE.
8607     *  The outgoing profile is:
8608     *      bool dvmCheckSuspendPending(Thread* self)
8609     *  Because we reached here via a call, go ahead and build a new frame.
8610     */
8611    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
8612    SPILL(rPC)                      # save edx
8613    push    %ebp
8614    movl    %esp,%ebp
8615    subl    $24,%esp
8616    movl    %eax,OUT_ARG0(%esp)
8617    call    dvmCheckSuspendPending
8618    addl    $24,%esp
8619    pop     %ebp
8620    UNSPILL(rPC)
8621    GET_GLUE(%ecx)
8622    ret
8623
8624    /* Switch interpreters */
8625    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
8626     * "complete" the interpretation of backwards branches.  In effect, we
8627     * are completing the interpretation of the branch instruction here,
8628     * and the new interpreter will resume interpretation at the branch
8629     * target. However, a switch request recognized during the handling
8630     * of a return from method instruction results in an immediate abort,
8631     * and the new interpreter will resume by re-interpreting the return
8632     * instruction.
8633     */
86343:
8635    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
8636    GET_GLUE(%ecx)                 # bail expect GLUE already loaded
8637    movl    $1,rINST_FULL         # set changeInterp to true
8638    jmp     common_gotoBail
8639
8640
8641/*
8642 * Common code for handling a return instruction
8643 */
8644common_returnFromMethod:
8645    GET_GLUE(%ecx)
8646    /* Set entry mode in case we bail */
8647    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
8648    xorl    rINST_FULL,rINST_FULL   # zero offset in case we switch interps
8649    call    common_periodicChecks   # Note: expects %ecx to be preserved
8650
8651    SAVEAREA_FROM_FP(%eax,rFP)                    # eax<- saveArea (old)
8652    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
8653    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
8654    cmpl    $0,rINST_FULL                        # break?
8655    je      common_gotoBail    # break frame, bail out completely
8656
8657    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
8658    movl    offGlue_self(%ecx),%eax               # eax<- self
8659    movl    rINST_FULL,offGlue_method(%ecx)  # glue->method = newSave->meethod
8660    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
8661    movl    offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
8662    FETCH_INST_WORD(3)
8663    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
8664    ADVANCE_PC(3)
8665    movl    %eax,offGlue_methodClassDex(%ecx)
8666    /* not bailing - restore entry mode to default */
8667    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8668    GOTO_NEXT
8669
8670/*
8671 * Prepare to strip the current frame and "longjump" back to caller of
8672 * dvmMterpStdRun.
8673 *
8674 * on entry:
8675 *    rINST_FULL holds changeInterp
8676 *    ecx holds glue pointer
8677 *
8678 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
8679 */
8680common_gotoBail:
8681    SAVE_PC_TO_GLUE(%ecx)                # export state to glue
8682    SAVE_FP_TO_GLUE(%ecx)
8683    movl   %ecx,OUT_ARG0(%esp)           # glue in arg0
8684    movl   rINST_FULL,OUT_ARG1(%esp)     # changeInterp in arg1
8685    call    dvmMterpStdBail              # bail out....
8686
8687
8688/*
8689 * After returning from a "glued" function, pull out the updated values
8690 * and start executing at the next instruction.
8691 */
8692 common_resumeAfterGlueCall:
8693     GET_GLUE(%ecx)
8694     LOAD_PC_FROM_GLUE(%ecx)
8695     LOAD_FP_FROM_GLUE(%ecx)
8696     FETCH_INST()
8697     GOTO_NEXT
8698
8699/*
8700 * Integer divide or mod by zero
8701 */
8702common_errDivideByZero:
8703    EXPORT_PC()
8704    movl    $.LstrArithmeticException,%eax
8705    movl    %eax,OUT_ARG0(%esp)
8706    movl    $.LstrDivideByZero,%eax
8707    movl    %eax,OUT_ARG1(%esp)
8708    SPILL(rPC)
8709    call    dvmThrowException
8710    UNSPILL(rPC)
8711    jmp     common_exceptionThrown
8712
8713/*
8714 * Attempt to allocate an array with a negative size.
8715 */
8716common_errNegativeArraySize:
8717    EXPORT_PC()
8718    movl    $.LstrNegativeArraySizeException,%eax
8719    movl    %eax,OUT_ARG0(%esp)
8720    xorl    %eax,%eax
8721    movl    %eax,OUT_ARG1(%esp)
8722    SPILL(rPC)
8723    call    dvmThrowException
8724    UNSPILL(rPC)
8725    jmp     common_exceptionThrown
8726
8727/*
8728 * Attempt to allocate an array with a negative size.
8729 */
8730common_errNoSuchMethod:
8731
8732    EXPORT_PC()
8733    movl    $.LstrNoSuchMethodError,%eax
8734    movl    %eax,OUT_ARG0(%esp)
8735    xorl    %eax,%eax
8736    movl    %eax,OUT_ARG1(%esp)
8737    SPILL(rPC)
8738    call    dvmThrowException
8739    UNSPILL(rPC)
8740    jmp     common_exceptionThrown
8741
8742/*
8743 * Hit a null object when we weren't expecting one.  Export the PC, throw a
8744 * NullPointerException and goto the exception processing code.
8745 */
8746common_errNullObject:
8747    EXPORT_PC()
8748    movl    $.LstrNullPointerException,%eax
8749    movl    %eax,OUT_ARG0(%esp)
8750    xorl    %eax,%eax
8751    movl    %eax,OUT_ARG1(%esp)
8752    SPILL(rPC)
8753    call    dvmThrowException
8754    UNSPILL(rPC)
8755    jmp     common_exceptionThrown
8756
8757/*
8758 * Array index exceeds max.
8759 */
8760common_errArrayIndex:
8761    EXPORT_PC()
8762    movl    $.LstrArrayIndexException,%eax
8763    movl    %eax,OUT_ARG0(%esp)
8764    xorl    %eax,%eax
8765    movl    %eax,OUT_ARG1(%esp)
8766    SPILL(rPC)
8767    call    dvmThrowException
8768    UNSPILL(rPC)
8769    jmp     common_exceptionThrown
8770/*
8771 * Invalid array value.
8772 */
8773common_errArrayStore:
8774    EXPORT_PC()
8775    movl    $.LstrArrayStoreException,%eax
8776    movl    %eax,OUT_ARG0(%esp)
8777    xorl    %eax,%eax
8778    movl    %eax,OUT_ARG1(%esp)
8779    SPILL(rPC)
8780    call    dvmThrowException
8781    UNSPILL(rPC)
8782    jmp     common_exceptionThrown
8783
8784/*
8785 * Somebody has thrown an exception.  Handle it.
8786 *
8787 * If the exception processing code returns to us (instead of falling
8788 * out of the interpreter), continue with whatever the next instruction
8789 * now happens to be.
8790 *
8791 * This does not return.
8792 */
8793common_exceptionThrown:
8794    GET_GLUE(%ecx)
8795    SAVE_PC_TO_GLUE(%ecx)
8796    SAVE_FP_TO_GLUE(%ecx)
8797    movl    %ecx,OUT_ARG0(%esp)
8798    call    dvmMterp_exceptionThrown
8799    jmp     common_resumeAfterGlueCall
8800
8801common_abort:
8802    movl    $0xdeadf00d,%eax
8803    call     *%eax
8804
8805
8806/*
8807 * Strings
8808 */
8809
8810    .section     .rodata
8811.LstrNullPointerException:
8812    .asciz    "Ljava/lang/NullPointerException;"
8813.LstrArithmeticException:
8814    .asciz  "Ljava/lang/ArithmeticException;"
8815.LstrDivideByZero:
8816    .asciz  "divide by zero"
8817.LstrArrayIndexException:
8818    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
8819.LstrArrayStoreException:
8820    .asciz  "Ljava/lang/ArrayStoreException;"
8821.LstrNegativeArraySizeException:
8822    .asciz  "Ljava/lang/NegativeArraySizeException;"
8823.LstrInstantiationError:
8824    .asciz  "Ljava/lang/InstantiationError;"
8825.LstrClassCastException:
8826    .asciz  "Ljava/lang/ClassCastException;"
8827.LstrNoSuchMethodError:
8828    .asciz  "Ljava/lang/NoSuchMethodError;"
8829.LstrInternalError:
8830    .asciz  "Ljava/lang/InternalError;"
8831.LstrFilledNewArrayNotImpl:
8832    .asciz  "filled-new-array only implemented for 'int'"
8833
8834
8835