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