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