InterpAsm-x86.S revision 3d95064ad1d8e6da4f9a523b2c2f11cf1f1ea952
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
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
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,OUT_ARG1(%esp)
6957    movl      %ecx,OUT_ARG0(%esp)
6958    call      dvmCanPutArrayElement     # test object type vs. array type
6959    UNSPILL(rPC)
6960    UNSPILL_TMP(%ecx)
6961    testl     %eax,%eax
6962    GET_GLUE(%eax)
6963    je        common_errArrayStore
6964    movl      offGlue_cardTable(%eax),%eax   # get card table base
6965    movl      rINST_FULL,(%ecx)
6966    FETCH_INST_WORD(2)
6967    shrl      $GC_CARD_SHIFT,%ecx           # convert addr to card number
6968    movb      %al,(%eax,%ecx)                # mark card
6969    ADVANCE_PC(2)
6970    GOTO_NEXT
6971
6972.LOP_APUT_OBJECT_skip_check:
6973    movl      rINST_FULL,(%ecx)
6974    FETCH_INST_WORD(2)
6975    ADVANCE_PC(2)
6976    GOTO_NEXT
6977
6978/* continuation for OP_IGET */
6979
6980
6981.LOP_IGET_resolve:
6982    EXPORT_PC()
6983    SPILL(rPC)
6984    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6985    UNSPILL(rIBASE)
6986    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6987    SPILL_TMP(%ecx)                               # save object pointer across call
6988    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6989    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6990    UNSPILL_TMP(%ecx)
6991    UNSPILL(rPC)
6992    testl   %eax,%eax                             #  ... which returns InstrField ptr
6993    jne     .LOP_IGET_finish
6994    jmp     common_exceptionThrown
6995
6996.LOP_IGET_finish:
6997    /*
6998     * Currently:
6999     *   eax holds resolved field
7000     *   ecx holds object
7001     *   rIBASE is scratch, but needs to be unspilled
7002     *   rINST_FULL holds A
7003     */
7004    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7005    UNSPILL(rIBASE)
7006    testl   %ecx,%ecx                            # object null?
7007    je      common_errNullObject                 # object was null
7008    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7009    movl    rINST_FULL,%eax                      # eax<- A
7010    FETCH_INST_WORD(2)
7011    SET_VREG(%ecx,%eax)
7012    ADVANCE_PC(2)
7013    GOTO_NEXT
7014
7015/* continuation for OP_IGET_WIDE */
7016
7017
7018.LOP_IGET_WIDE_resolve:
7019    EXPORT_PC()
7020    SPILL(rPC)
7021    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7022    UNSPILL(rIBASE)
7023    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7024    SPILL_TMP(%ecx)                               # save object pointer across call
7025    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7026    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7027    UNSPILL_TMP(%ecx)
7028    UNSPILL(rPC)
7029    testl   %eax,%eax                             #  ... which returns InstrField ptr
7030    jne     .LOP_IGET_WIDE_finish
7031    jmp     common_exceptionThrown
7032
7033.LOP_IGET_WIDE_finish:
7034    /*
7035     * Currently:
7036     *   eax holds resolved field
7037     *   ecx holds object
7038     *   rIBASE is scratch, but needs to be unspilled
7039     *   rINST_FULL holds A
7040     */
7041    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7042    UNSPILL(rIBASE)
7043    testl   %ecx,%ecx                            # object null?
7044    je      common_errNullObject                 # object was null
7045    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
7046    movl    (%eax),%ecx                          # ecx<- lsw
7047    movl    4(%eax),%eax                         # eax<- msw
7048    SET_VREG_WORD(%ecx,rINST_FULL,0)
7049    SET_VREG_WORD(%eax,rINST_FULL,1)
7050    FETCH_INST_WORD(2)
7051    ADVANCE_PC(2)
7052    GOTO_NEXT
7053
7054/* continuation for OP_IGET_OBJECT */
7055
7056
7057.LOP_IGET_OBJECT_resolve:
7058    EXPORT_PC()
7059    SPILL(rPC)
7060    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7061    UNSPILL(rIBASE)
7062    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7063    SPILL_TMP(%ecx)                               # save object pointer across call
7064    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7065    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7066    UNSPILL_TMP(%ecx)
7067    UNSPILL(rPC)
7068    testl   %eax,%eax                             #  ... which returns InstrField ptr
7069    jne     .LOP_IGET_OBJECT_finish
7070    jmp     common_exceptionThrown
7071
7072.LOP_IGET_OBJECT_finish:
7073    /*
7074     * Currently:
7075     *   eax holds resolved field
7076     *   ecx holds object
7077     *   rIBASE is scratch, but needs to be unspilled
7078     *   rINST_FULL holds A
7079     */
7080    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7081    UNSPILL(rIBASE)
7082    testl   %ecx,%ecx                            # object null?
7083    je      common_errNullObject                 # object was null
7084    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7085    movl    rINST_FULL,%eax                      # eax<- A
7086    FETCH_INST_WORD(2)
7087    SET_VREG(%ecx,%eax)
7088    ADVANCE_PC(2)
7089    GOTO_NEXT
7090
7091/* continuation for OP_IGET_BOOLEAN */
7092
7093
7094.LOP_IGET_BOOLEAN_resolve:
7095    EXPORT_PC()
7096    SPILL(rPC)
7097    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7098    UNSPILL(rIBASE)
7099    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7100    SPILL_TMP(%ecx)                               # save object pointer across call
7101    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7102    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7103    UNSPILL_TMP(%ecx)
7104    UNSPILL(rPC)
7105    testl   %eax,%eax                             #  ... which returns InstrField ptr
7106    jne     .LOP_IGET_BOOLEAN_finish
7107    jmp     common_exceptionThrown
7108
7109.LOP_IGET_BOOLEAN_finish:
7110    /*
7111     * Currently:
7112     *   eax holds resolved field
7113     *   ecx holds object
7114     *   rIBASE is scratch, but needs to be unspilled
7115     *   rINST_FULL holds A
7116     */
7117    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7118    UNSPILL(rIBASE)
7119    testl   %ecx,%ecx                            # object null?
7120    je      common_errNullObject                 # object was null
7121    movzbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7122    movl    rINST_FULL,%eax                      # eax<- A
7123    FETCH_INST_WORD(2)
7124    SET_VREG(%ecx,%eax)
7125    ADVANCE_PC(2)
7126    GOTO_NEXT
7127
7128/* continuation for OP_IGET_BYTE */
7129
7130
7131.LOP_IGET_BYTE_resolve:
7132    EXPORT_PC()
7133    SPILL(rPC)
7134    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7135    UNSPILL(rIBASE)
7136    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7137    SPILL_TMP(%ecx)                               # save object pointer across call
7138    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7139    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7140    UNSPILL_TMP(%ecx)
7141    UNSPILL(rPC)
7142    testl   %eax,%eax                             #  ... which returns InstrField ptr
7143    jne     .LOP_IGET_BYTE_finish
7144    jmp     common_exceptionThrown
7145
7146.LOP_IGET_BYTE_finish:
7147    /*
7148     * Currently:
7149     *   eax holds resolved field
7150     *   ecx holds object
7151     *   rIBASE is scratch, but needs to be unspilled
7152     *   rINST_FULL holds A
7153     */
7154    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7155    UNSPILL(rIBASE)
7156    testl   %ecx,%ecx                            # object null?
7157    je      common_errNullObject                 # object was null
7158    movsbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7159    movl    rINST_FULL,%eax                      # eax<- A
7160    FETCH_INST_WORD(2)
7161    SET_VREG(%ecx,%eax)
7162    ADVANCE_PC(2)
7163    GOTO_NEXT
7164
7165/* continuation for OP_IGET_CHAR */
7166
7167
7168.LOP_IGET_CHAR_resolve:
7169    EXPORT_PC()
7170    SPILL(rPC)
7171    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7172    UNSPILL(rIBASE)
7173    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7174    SPILL_TMP(%ecx)                               # save object pointer across call
7175    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7176    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7177    UNSPILL_TMP(%ecx)
7178    UNSPILL(rPC)
7179    testl   %eax,%eax                             #  ... which returns InstrField ptr
7180    jne     .LOP_IGET_CHAR_finish
7181    jmp     common_exceptionThrown
7182
7183.LOP_IGET_CHAR_finish:
7184    /*
7185     * Currently:
7186     *   eax holds resolved field
7187     *   ecx holds object
7188     *   rIBASE is scratch, but needs to be unspilled
7189     *   rINST_FULL holds A
7190     */
7191    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7192    UNSPILL(rIBASE)
7193    testl   %ecx,%ecx                            # object null?
7194    je      common_errNullObject                 # object was null
7195    movzwl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7196    movl    rINST_FULL,%eax                      # eax<- A
7197    FETCH_INST_WORD(2)
7198    SET_VREG(%ecx,%eax)
7199    ADVANCE_PC(2)
7200    GOTO_NEXT
7201
7202/* continuation for OP_IGET_SHORT */
7203
7204
7205.LOP_IGET_SHORT_resolve:
7206    EXPORT_PC()
7207    SPILL(rPC)
7208    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7209    UNSPILL(rIBASE)
7210    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7211    SPILL_TMP(%ecx)                               # save object pointer across call
7212    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7213    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7214    UNSPILL_TMP(%ecx)
7215    UNSPILL(rPC)
7216    testl   %eax,%eax                             #  ... which returns InstrField ptr
7217    jne     .LOP_IGET_SHORT_finish
7218    jmp     common_exceptionThrown
7219
7220.LOP_IGET_SHORT_finish:
7221    /*
7222     * Currently:
7223     *   eax holds resolved field
7224     *   ecx holds object
7225     *   rIBASE is scratch, but needs to be unspilled
7226     *   rINST_FULL holds A
7227     */
7228    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7229    UNSPILL(rIBASE)
7230    testl   %ecx,%ecx                            # object null?
7231    je      common_errNullObject                 # object was null
7232    movswl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7233    movl    rINST_FULL,%eax                      # eax<- A
7234    FETCH_INST_WORD(2)
7235    SET_VREG(%ecx,%eax)
7236    ADVANCE_PC(2)
7237    GOTO_NEXT
7238
7239/* continuation for OP_IPUT */
7240
7241
7242.LOP_IPUT_resolve:
7243    EXPORT_PC()
7244    SPILL(rPC)
7245    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7246    UNSPILL(rIBASE)
7247    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7248    SPILL_TMP(%ecx)                               # save object pointer across call
7249    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7250    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7251    UNSPILL_TMP(%ecx)
7252    UNSPILL(rPC)
7253    testl   %eax,%eax                             #  ... which returns InstrField ptr
7254    jne     .LOP_IPUT_finish
7255    jmp     common_exceptionThrown
7256
7257.LOP_IPUT_finish:
7258    /*
7259     * Currently:
7260     *   eax holds resolved field
7261     *   ecx holds object
7262     *   rIBASE is scratch, but needs to be unspilled
7263     *   rINST_FULL holds A
7264     */
7265    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7266    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7267    UNSPILL(rIBASE)
7268    testl   %ecx,%ecx                            # object null?
7269    je      common_errNullObject                 # object was null
7270    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7271    FETCH_INST_WORD(2)
7272    ADVANCE_PC(2)
7273    GOTO_NEXT
7274
7275/* continuation for OP_IPUT_WIDE */
7276
7277
7278.LOP_IPUT_WIDE_resolve:
7279    EXPORT_PC()
7280    SPILL(rPC)
7281    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7282    UNSPILL(rIBASE)
7283    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7284    SPILL_TMP(%ecx)                               # save object pointer across call
7285    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7286    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7287    UNSPILL_TMP(%ecx)
7288    UNSPILL(rPC)
7289    testl   %eax,%eax                             #  ... which returns InstrField ptr
7290    jne     .LOP_IPUT_WIDE_finish
7291    jmp     common_exceptionThrown
7292
7293.LOP_IPUT_WIDE_finish:
7294    /*
7295     * Currently:
7296     *   eax holds resolved field
7297     *   ecx holds object
7298     *   rIBASE is scratch, but needs to be unspilled
7299     *   rINST_FULL holds A
7300     */
7301    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7302    UNSPILL(rIBASE)
7303    testl   %ecx,%ecx                            # object null?
7304    je      common_errNullObject                 # object was null
7305    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
7306    GET_VREG_WORD(%ecx,rINST_FULL,0)             # ecx<- lsw
7307    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)       # rINST_FULL<- msw
7308    movl    rINST_FULL,4(%eax)
7309    FETCH_INST_WORD(2)
7310    movl    %ecx,(%eax)
7311    ADVANCE_PC(2)
7312    GOTO_NEXT
7313
7314/* continuation for OP_IPUT_OBJECT */
7315
7316
7317.LOP_IPUT_OBJECT_resolve:
7318    EXPORT_PC()
7319    SPILL(rPC)
7320    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7321    UNSPILL(rIBASE)
7322    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7323    SPILL_TMP(%ecx)                               # save object pointer across call
7324    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7325    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7326    UNSPILL_TMP(%ecx)
7327    UNSPILL(rPC)
7328    testl   %eax,%eax                             #  ... which returns InstrField ptr
7329    jne     .LOP_IPUT_OBJECT_finish
7330    jmp     common_exceptionThrown
7331
7332.LOP_IPUT_OBJECT_finish:
7333    /*
7334     * Currently:
7335     *   eax holds resolved field
7336     *   ecx holds object
7337     *   rIBASE is scratch, but needs to be unspilled
7338     *   rINST_FULL holds A
7339     */
7340    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7341    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7342    UNSPILL(rIBASE)
7343    testl   %ecx,%ecx                            # object null?
7344    je      common_errNullObject                 # object was null
7345    movl    rINST_FULL,(%ecx,%eax)          # obj.field <- v[A](8/16/32 bits)
7346    GET_GLUE(%eax)
7347    testl   rINST_FULL,rINST_FULL                # stored a NULL?
7348    movl    offGlue_cardTable(%eax),%eax         # get card table base
7349    FETCH_INST_WORD(2)
7350    je      1f                                   # skip card mark if null store
7351    shrl    $GC_CARD_SHIFT,%ecx                 # object head to card number
7352    movb    %al,(%eax,%ecx)                      # mark card
73531:
7354    ADVANCE_PC(2)
7355    GOTO_NEXT
7356
7357/* continuation for OP_IPUT_BOOLEAN */
7358
7359
7360.LOP_IPUT_BOOLEAN_resolve:
7361    EXPORT_PC()
7362    SPILL(rPC)
7363    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7364    UNSPILL(rIBASE)
7365    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7366    SPILL_TMP(%ecx)                               # save object pointer across call
7367    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7368    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7369    UNSPILL_TMP(%ecx)
7370    UNSPILL(rPC)
7371    testl   %eax,%eax                             #  ... which returns InstrField ptr
7372    jne     .LOP_IPUT_BOOLEAN_finish
7373    jmp     common_exceptionThrown
7374
7375.LOP_IPUT_BOOLEAN_finish:
7376    /*
7377     * Currently:
7378     *   eax holds resolved field
7379     *   ecx holds object
7380     *   rIBASE is scratch, but needs to be unspilled
7381     *   rINST_FULL holds A
7382     */
7383    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7384    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7385    UNSPILL(rIBASE)
7386    testl   %ecx,%ecx                            # object null?
7387    je      common_errNullObject                 # object was null
7388    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7389    FETCH_INST_WORD(2)
7390    ADVANCE_PC(2)
7391    GOTO_NEXT
7392
7393/* continuation for OP_IPUT_BYTE */
7394
7395
7396.LOP_IPUT_BYTE_resolve:
7397    EXPORT_PC()
7398    SPILL(rPC)
7399    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7400    UNSPILL(rIBASE)
7401    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7402    SPILL_TMP(%ecx)                               # save object pointer across call
7403    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7404    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7405    UNSPILL_TMP(%ecx)
7406    UNSPILL(rPC)
7407    testl   %eax,%eax                             #  ... which returns InstrField ptr
7408    jne     .LOP_IPUT_BYTE_finish
7409    jmp     common_exceptionThrown
7410
7411.LOP_IPUT_BYTE_finish:
7412    /*
7413     * Currently:
7414     *   eax holds resolved field
7415     *   ecx holds object
7416     *   rIBASE is scratch, but needs to be unspilled
7417     *   rINST_FULL holds A
7418     */
7419    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7420    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7421    UNSPILL(rIBASE)
7422    testl   %ecx,%ecx                            # object null?
7423    je      common_errNullObject                 # object was null
7424    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7425    FETCH_INST_WORD(2)
7426    ADVANCE_PC(2)
7427    GOTO_NEXT
7428
7429/* continuation for OP_IPUT_CHAR */
7430
7431
7432.LOP_IPUT_CHAR_resolve:
7433    EXPORT_PC()
7434    SPILL(rPC)
7435    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7436    UNSPILL(rIBASE)
7437    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7438    SPILL_TMP(%ecx)                               # save object pointer across call
7439    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7440    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7441    UNSPILL_TMP(%ecx)
7442    UNSPILL(rPC)
7443    testl   %eax,%eax                             #  ... which returns InstrField ptr
7444    jne     .LOP_IPUT_CHAR_finish
7445    jmp     common_exceptionThrown
7446
7447.LOP_IPUT_CHAR_finish:
7448    /*
7449     * Currently:
7450     *   eax holds resolved field
7451     *   ecx holds object
7452     *   rIBASE is scratch, but needs to be unspilled
7453     *   rINST_FULL holds A
7454     */
7455    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7456    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7457    UNSPILL(rIBASE)
7458    testl   %ecx,%ecx                            # object null?
7459    je      common_errNullObject                 # object was null
7460    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7461    FETCH_INST_WORD(2)
7462    ADVANCE_PC(2)
7463    GOTO_NEXT
7464
7465/* continuation for OP_IPUT_SHORT */
7466
7467
7468.LOP_IPUT_SHORT_resolve:
7469    EXPORT_PC()
7470    SPILL(rPC)
7471    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7472    UNSPILL(rIBASE)
7473    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7474    SPILL_TMP(%ecx)                               # save object pointer across call
7475    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7476    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7477    UNSPILL_TMP(%ecx)
7478    UNSPILL(rPC)
7479    testl   %eax,%eax                             #  ... which returns InstrField ptr
7480    jne     .LOP_IPUT_SHORT_finish
7481    jmp     common_exceptionThrown
7482
7483.LOP_IPUT_SHORT_finish:
7484    /*
7485     * Currently:
7486     *   eax holds resolved field
7487     *   ecx holds object
7488     *   rIBASE is scratch, but needs to be unspilled
7489     *   rINST_FULL holds A
7490     */
7491    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7492    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7493    UNSPILL(rIBASE)
7494    testl   %ecx,%ecx                            # object null?
7495    je      common_errNullObject                 # object was null
7496    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7497    FETCH_INST_WORD(2)
7498    ADVANCE_PC(2)
7499    GOTO_NEXT
7500
7501/* continuation for OP_SGET */
7502
7503    /*
7504     * Go resolve the field
7505     */
7506.LOP_SGET_resolve:
7507    GET_GLUE(%ecx)
7508    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7509    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7510    EXPORT_PC()                                 # could throw, need to export
7511    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7512    SPILL(rPC)
7513    movl     %eax,OUT_ARG1(%esp)
7514    movl     %ecx,OUT_ARG0(%esp)
7515    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7516    UNSPILL(rPC)
7517    testl    %eax,%eax
7518    jne      .LOP_SGET_finish                 # success, continue
7519    jmp      common_exceptionThrown             # no, handle exception
7520
7521/* continuation for OP_SGET_WIDE */
7522
7523    /*
7524     * Go resolve the field
7525     */
7526.LOP_SGET_WIDE_resolve:
7527    GET_GLUE(%ecx)
7528    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7529    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7530    EXPORT_PC()                                 # could throw, need to export
7531    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7532    SPILL(rPC)
7533    movl     %eax,OUT_ARG1(%esp)
7534    movl     %ecx,OUT_ARG0(%esp)
7535    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7536    UNSPILL(rPC)
7537    testl    %eax,%eax
7538    jne      .LOP_SGET_WIDE_finish                 # success, continue
7539    jmp      common_exceptionThrown             # no, handle exception
7540
7541/* continuation for OP_SGET_OBJECT */
7542
7543    /*
7544     * Go resolve the field
7545     */
7546.LOP_SGET_OBJECT_resolve:
7547    GET_GLUE(%ecx)
7548    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7549    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7550    EXPORT_PC()                                 # could throw, need to export
7551    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7552    SPILL(rPC)
7553    movl     %eax,OUT_ARG1(%esp)
7554    movl     %ecx,OUT_ARG0(%esp)
7555    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7556    UNSPILL(rPC)
7557    testl    %eax,%eax
7558    jne      .LOP_SGET_OBJECT_finish                 # success, continue
7559    jmp      common_exceptionThrown             # no, handle exception
7560
7561/* continuation for OP_SGET_BOOLEAN */
7562
7563    /*
7564     * Go resolve the field
7565     */
7566.LOP_SGET_BOOLEAN_resolve:
7567    GET_GLUE(%ecx)
7568    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7569    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7570    EXPORT_PC()                                 # could throw, need to export
7571    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7572    SPILL(rPC)
7573    movl     %eax,OUT_ARG1(%esp)
7574    movl     %ecx,OUT_ARG0(%esp)
7575    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7576    UNSPILL(rPC)
7577    testl    %eax,%eax
7578    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
7579    jmp      common_exceptionThrown             # no, handle exception
7580
7581/* continuation for OP_SGET_BYTE */
7582
7583    /*
7584     * Go resolve the field
7585     */
7586.LOP_SGET_BYTE_resolve:
7587    GET_GLUE(%ecx)
7588    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7589    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7590    EXPORT_PC()                                 # could throw, need to export
7591    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7592    SPILL(rPC)
7593    movl     %eax,OUT_ARG1(%esp)
7594    movl     %ecx,OUT_ARG0(%esp)
7595    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7596    UNSPILL(rPC)
7597    testl    %eax,%eax
7598    jne      .LOP_SGET_BYTE_finish                 # success, continue
7599    jmp      common_exceptionThrown             # no, handle exception
7600
7601/* continuation for OP_SGET_CHAR */
7602
7603    /*
7604     * Go resolve the field
7605     */
7606.LOP_SGET_CHAR_resolve:
7607    GET_GLUE(%ecx)
7608    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7609    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7610    EXPORT_PC()                                 # could throw, need to export
7611    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7612    SPILL(rPC)
7613    movl     %eax,OUT_ARG1(%esp)
7614    movl     %ecx,OUT_ARG0(%esp)
7615    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7616    UNSPILL(rPC)
7617    testl    %eax,%eax
7618    jne      .LOP_SGET_CHAR_finish                 # success, continue
7619    jmp      common_exceptionThrown             # no, handle exception
7620
7621/* continuation for OP_SGET_SHORT */
7622
7623    /*
7624     * Go resolve the field
7625     */
7626.LOP_SGET_SHORT_resolve:
7627    GET_GLUE(%ecx)
7628    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7629    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7630    EXPORT_PC()                                 # could throw, need to export
7631    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7632    SPILL(rPC)
7633    movl     %eax,OUT_ARG1(%esp)
7634    movl     %ecx,OUT_ARG0(%esp)
7635    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7636    UNSPILL(rPC)
7637    testl    %eax,%eax
7638    jne      .LOP_SGET_SHORT_finish                 # success, continue
7639    jmp      common_exceptionThrown             # no, handle exception
7640
7641/* continuation for OP_SPUT */
7642
7643    /*
7644     * Go resolve the field
7645     */
7646.LOP_SPUT_resolve:
7647    GET_GLUE(%ecx)
7648    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7649    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7650    EXPORT_PC()                                 # could throw, need to export
7651    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7652    SPILL(rPC)
7653    movl     %eax,OUT_ARG1(%esp)
7654    movl     %ecx,OUT_ARG0(%esp)
7655    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7656    UNSPILL(rPC)
7657    testl    %eax,%eax
7658    jne      .LOP_SPUT_finish                 # success, continue
7659    jmp      common_exceptionThrown             # no, handle exception
7660
7661/* continuation for OP_SPUT_WIDE */
7662
7663    /*
7664     * Go resolve the field
7665     */
7666.LOP_SPUT_WIDE_resolve:
7667    GET_GLUE(%ecx)
7668    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7669    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7670    EXPORT_PC()                                 # could throw, need to export
7671    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7672    SPILL(rPC)
7673    movl     %eax,OUT_ARG1(%esp)
7674    movl     %ecx,OUT_ARG0(%esp)
7675    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7676    UNSPILL(rPC)
7677    testl    %eax,%eax
7678    jne      .LOP_SPUT_WIDE_finish                 # success, continue
7679    jmp      common_exceptionThrown             # no, handle exception
7680
7681/* continuation for OP_SPUT_OBJECT */
7682
7683
7684.LOP_SPUT_OBJECT_continue:
7685    movl      %ecx,offStaticField_value(%eax)
7686    testl     %ecx,%ecx
7687    GET_GLUE(%ecx)
7688    FETCH_INST_WORD(2)
7689    je        1f
7690    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
7691    shrl      $GC_CARD_SHIFT,%eax               # head to card number
7692    movb      %cl,(%ecx,%eax)                    # mark card
76931:
7694    ADVANCE_PC(2)
7695    GOTO_NEXT
7696
7697.LOP_SPUT_OBJECT_resolve:
7698    GET_GLUE(%ecx)
7699    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7700    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7701    EXPORT_PC()                                 # could throw, need to export
7702    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7703    SPILL(rPC)
7704    movl     %eax,OUT_ARG1(%esp)
7705    movl     %ecx,OUT_ARG0(%esp)
7706    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7707    UNSPILL(rPC)
7708    testl    %eax,%eax
7709    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
7710    jmp      common_exceptionThrown             # no, handle exception
7711
7712/* continuation for OP_SPUT_BOOLEAN */
7713
7714    /*
7715     * Go resolve the field
7716     */
7717.LOP_SPUT_BOOLEAN_resolve:
7718    GET_GLUE(%ecx)
7719    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7720    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7721    EXPORT_PC()                                 # could throw, need to export
7722    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7723    SPILL(rPC)
7724    movl     %eax,OUT_ARG1(%esp)
7725    movl     %ecx,OUT_ARG0(%esp)
7726    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7727    UNSPILL(rPC)
7728    testl    %eax,%eax
7729    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
7730    jmp      common_exceptionThrown             # no, handle exception
7731
7732/* continuation for OP_SPUT_BYTE */
7733
7734    /*
7735     * Go resolve the field
7736     */
7737.LOP_SPUT_BYTE_resolve:
7738    GET_GLUE(%ecx)
7739    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7740    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7741    EXPORT_PC()                                 # could throw, need to export
7742    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7743    SPILL(rPC)
7744    movl     %eax,OUT_ARG1(%esp)
7745    movl     %ecx,OUT_ARG0(%esp)
7746    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7747    UNSPILL(rPC)
7748    testl    %eax,%eax
7749    jne      .LOP_SPUT_BYTE_finish                 # success, continue
7750    jmp      common_exceptionThrown             # no, handle exception
7751
7752/* continuation for OP_SPUT_CHAR */
7753
7754    /*
7755     * Go resolve the field
7756     */
7757.LOP_SPUT_CHAR_resolve:
7758    GET_GLUE(%ecx)
7759    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7760    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7761    EXPORT_PC()                                 # could throw, need to export
7762    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7763    SPILL(rPC)
7764    movl     %eax,OUT_ARG1(%esp)
7765    movl     %ecx,OUT_ARG0(%esp)
7766    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7767    UNSPILL(rPC)
7768    testl    %eax,%eax
7769    jne      .LOP_SPUT_CHAR_finish                 # success, continue
7770    jmp      common_exceptionThrown             # no, handle exception
7771
7772/* continuation for OP_SPUT_SHORT */
7773
7774    /*
7775     * Go resolve the field
7776     */
7777.LOP_SPUT_SHORT_resolve:
7778    GET_GLUE(%ecx)
7779    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7780    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7781    EXPORT_PC()                                 # could throw, need to export
7782    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7783    SPILL(rPC)
7784    movl     %eax,OUT_ARG1(%esp)
7785    movl     %ecx,OUT_ARG0(%esp)
7786    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7787    UNSPILL(rPC)
7788    testl    %eax,%eax
7789    jne      .LOP_SPUT_SHORT_finish                 # success, continue
7790    jmp      common_exceptionThrown             # no, handle exception
7791
7792/* continuation for OP_INVOKE_VIRTUAL */
7793
7794
7795.LOP_INVOKE_VIRTUAL_more:
7796    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7797    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7798    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7799    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7800    UNSPILL(rPC)
7801    testl     %eax,%eax                   # got null?
7802    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
7803    jmp       common_exceptionThrown      # yes, handle exception
7804
7805    /* At this point:
7806     *   eax = resolved base method
7807     *   ecx = scratch
7808     */
7809.LOP_INVOKE_VIRTUAL_continue:
7810    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7811    .if       (!0)
7812    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7813    .endif
7814    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7815    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7816    testl     %ecx,%ecx                 # null this?
7817    je        common_errNullObject      # go if so
7818    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7819    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7820    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7821    jmp       common_invokeMethodNoRange
7822
7823/* continuation for OP_INVOKE_SUPER */
7824
7825    /*
7826     * At this point:
7827     *  ecx = resolved base method [r0]
7828     *  eax = method->clazz [r9]
7829     */
7830.LOP_INVOKE_SUPER_continue:
7831    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7832    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7833    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7834    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
7835    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7836    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7837    jmp     common_invokeMethodNoRange
7838
7839
7840    /* At this point:
7841     * ecx = null (needs to be resolved base method)
7842     * eax = method->clazz
7843    */
7844.LOP_INVOKE_SUPER_resolve:
7845    SPILL_TMP(%eax)                     # method->clazz
7846    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7847    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7848    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7849    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7850    SPILL(rPC)
7851    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7852    UNSPILL(rPC)
7853    testl   %eax,%eax                   # got null?
7854    movl    %eax,%ecx                   # ecx<- resolved base method
7855    UNSPILL_TMP(%eax)                   # restore method->clazz
7856    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
7857    jmp     common_exceptionThrown      # handle exception
7858
7859    /*
7860     * Throw a NoSuchMethodError with the method name as the message.
7861     *  ecx = resolved base method
7862     */
7863.LOP_INVOKE_SUPER_nsm:
7864    movl    offMethod_name(%ecx),%eax
7865    mov     %eax,OUT_ARG1(%esp)
7866    jmp     common_errNoSuchMethod
7867
7868/* continuation for OP_INVOKE_DIRECT */
7869
7870    /*
7871     * On entry:
7872     *   TMP_SPILL  <- "this" register
7873     * Things a bit ugly on this path, but it's the less
7874     * frequent one.  We'll have to do some reloading.
7875     */
7876.LOP_INVOKE_DIRECT_resolve:
7877     SPILL_TMP(%ecx)
7878     GET_GLUE(%ecx)
7879     UNSPILL(rPC)
7880     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7881     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7882     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7883     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7884     movl     %eax,OUT_ARG1(%esp)
7885     movl     %ecx,OUT_ARG0(%esp)
7886     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7887     UNSPILL_TMP(%ecx)
7888     testl    %eax,%eax
7889     jne      .LOP_INVOKE_DIRECT_finish
7890     UNSPILL(rPC)
7891     jmp      common_exceptionThrown
7892
7893/* continuation for OP_INVOKE_STATIC */
7894
7895.LOP_INVOKE_STATIC_continue:
7896    movl      $METHOD_STATIC,%eax
7897    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7898    SPILL(rPC)
7899    call      dvmResolveMethod          # call(clazz,ref,flags)
7900    UNSPILL(rPC)
7901    testl     %eax,%eax                 # got null?
7902    jne       common_invokeMethodNoRange
7903    jmp       common_exceptionThrown
7904
7905/* continuation for OP_INVOKE_INTERFACE */
7906
7907.LOP_INVOKE_INTERFACE_continue:
7908    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7909    UNSPILL(rPC)
7910    testl      %eax,%eax
7911    je         common_exceptionThrown
7912    jmp        common_invokeMethodNoRange
7913
7914/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7915
7916
7917.LOP_INVOKE_VIRTUAL_RANGE_more:
7918    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7919    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7920    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7921    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7922    UNSPILL(rPC)
7923    testl     %eax,%eax                   # got null?
7924    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
7925    jmp       common_exceptionThrown      # yes, handle exception
7926
7927    /* At this point:
7928     *   eax = resolved base method
7929     *   ecx = scratch
7930     */
7931.LOP_INVOKE_VIRTUAL_RANGE_continue:
7932    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7933    .if       (!1)
7934    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7935    .endif
7936    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7937    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7938    testl     %ecx,%ecx                 # null this?
7939    je        common_errNullObject      # go if so
7940    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7941    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7942    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7943    jmp       common_invokeMethodRange
7944
7945/* continuation for OP_INVOKE_SUPER_RANGE */
7946
7947    /*
7948     * At this point:
7949     *  ecx = resolved base method [r0]
7950     *  eax = method->clazz [r9]
7951     */
7952.LOP_INVOKE_SUPER_RANGE_continue:
7953    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7954    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7955    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7956    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
7957    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7958    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7959    jmp     common_invokeMethodRange
7960
7961
7962    /* At this point:
7963     * ecx = null (needs to be resolved base method)
7964     * eax = method->clazz
7965    */
7966.LOP_INVOKE_SUPER_RANGE_resolve:
7967    SPILL_TMP(%eax)                     # method->clazz
7968    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7969    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7970    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7971    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7972    SPILL(rPC)
7973    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7974    UNSPILL(rPC)
7975    testl   %eax,%eax                   # got null?
7976    movl    %eax,%ecx                   # ecx<- resolved base method
7977    UNSPILL_TMP(%eax)                   # restore method->clazz
7978    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
7979    jmp     common_exceptionThrown      # handle exception
7980
7981    /*
7982     * Throw a NoSuchMethodError with the method name as the message.
7983     *  ecx = resolved base method
7984     */
7985.LOP_INVOKE_SUPER_RANGE_nsm:
7986    movl    offMethod_name(%ecx),%eax
7987    mov     %eax,OUT_ARG1(%esp)
7988    jmp     common_errNoSuchMethod
7989
7990/* continuation for OP_INVOKE_DIRECT_RANGE */
7991
7992    /*
7993     * On entry:
7994     *   TMP_SPILL  <- "this" register
7995     * Things a bit ugly on this path, but it's the less
7996     * frequent one.  We'll have to do some reloading.
7997     */
7998.LOP_INVOKE_DIRECT_RANGE_resolve:
7999     SPILL_TMP(%ecx)
8000     GET_GLUE(%ecx)
8001     UNSPILL(rPC)
8002     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
8003     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
8004     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8005     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
8006     movl     %eax,OUT_ARG1(%esp)
8007     movl     %ecx,OUT_ARG0(%esp)
8008     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
8009     UNSPILL_TMP(%ecx)
8010     testl    %eax,%eax
8011     jne      .LOP_INVOKE_DIRECT_RANGE_finish
8012     UNSPILL(rPC)
8013     jmp      common_exceptionThrown
8014
8015/* continuation for OP_INVOKE_STATIC_RANGE */
8016
8017.LOP_INVOKE_STATIC_RANGE_continue:
8018    movl      $METHOD_STATIC,%eax
8019    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
8020    SPILL(rPC)
8021    call      dvmResolveMethod          # call(clazz,ref,flags)
8022    UNSPILL(rPC)
8023    testl     %eax,%eax                 # got null?
8024    jne       common_invokeMethodRange
8025    jmp       common_exceptionThrown
8026
8027/* continuation for OP_INVOKE_INTERFACE_RANGE */
8028
8029.LOP_INVOKE_INTERFACE_RANGE_continue:
8030    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
8031    UNSPILL(rPC)
8032    testl      %eax,%eax
8033    je         common_exceptionThrown
8034    jmp        common_invokeMethodRange
8035
8036/* continuation for OP_FLOAT_TO_INT */
8037
8038
8039.LOP_FLOAT_TO_INT_continue:
8040    .if 0
8041    movl     $0x80000000,%eax
8042    xorl     4(rFP,%ecx,4),%eax
8043    orl      (rFP,%ecx,4),%eax
8044    .else
8045    cmpl     $0x80000000,(rFP,%ecx,4)
8046    .endif
8047    je       .LOP_FLOAT_TO_INT_special_case # fix up result
8048
8049.LOP_FLOAT_TO_INT_finish:
8050    ADVANCE_PC(1)
8051    GOTO_NEXT
8052
8053.LOP_FLOAT_TO_INT_special_case:
8054    fnstsw   %ax
8055    sahf
8056    jp       .LOP_FLOAT_TO_INT_isNaN
8057    adcl     $-1,(rFP,%ecx,4)
8058    .if 0
8059    adcl     $-1,4(rFP,%ecx,4)
8060    .endif
8061   jmp       .LOP_FLOAT_TO_INT_finish
8062.LOP_FLOAT_TO_INT_isNaN:
8063    movl      $0,(rFP,%ecx,4)
8064    .if 0
8065    movl      $0,4(rFP,%ecx,4)
8066    .endif
8067    jmp       .LOP_FLOAT_TO_INT_finish
8068
8069/* continuation for OP_FLOAT_TO_LONG */
8070
8071
8072.LOP_FLOAT_TO_LONG_continue:
8073    .if 1
8074    movl     $0x80000000,%eax
8075    xorl     4(rFP,%ecx,4),%eax
8076    orl      (rFP,%ecx,4),%eax
8077    .else
8078    cmpl     $0x80000000,(rFP,%ecx,4)
8079    .endif
8080    je       .LOP_FLOAT_TO_LONG_special_case # fix up result
8081
8082.LOP_FLOAT_TO_LONG_finish:
8083    ADVANCE_PC(1)
8084    GOTO_NEXT
8085
8086.LOP_FLOAT_TO_LONG_special_case:
8087    fnstsw   %ax
8088    sahf
8089    jp       .LOP_FLOAT_TO_LONG_isNaN
8090    adcl     $-1,(rFP,%ecx,4)
8091    .if 1
8092    adcl     $-1,4(rFP,%ecx,4)
8093    .endif
8094   jmp       .LOP_FLOAT_TO_LONG_finish
8095.LOP_FLOAT_TO_LONG_isNaN:
8096    movl      $0,(rFP,%ecx,4)
8097    .if 1
8098    movl      $0,4(rFP,%ecx,4)
8099    .endif
8100    jmp       .LOP_FLOAT_TO_LONG_finish
8101
8102/* continuation for OP_DOUBLE_TO_INT */
8103
8104
8105.LOP_DOUBLE_TO_INT_continue:
8106    .if 0
8107    movl     $0x80000000,%eax
8108    xorl     4(rFP,%ecx,4),%eax
8109    orl      (rFP,%ecx,4),%eax
8110    .else
8111    cmpl     $0x80000000,(rFP,%ecx,4)
8112    .endif
8113    je       .LOP_DOUBLE_TO_INT_special_case # fix up result
8114
8115.LOP_DOUBLE_TO_INT_finish:
8116    ADVANCE_PC(1)
8117    GOTO_NEXT
8118
8119.LOP_DOUBLE_TO_INT_special_case:
8120    fnstsw   %ax
8121    sahf
8122    jp       .LOP_DOUBLE_TO_INT_isNaN
8123    adcl     $-1,(rFP,%ecx,4)
8124    .if 0
8125    adcl     $-1,4(rFP,%ecx,4)
8126    .endif
8127   jmp       .LOP_DOUBLE_TO_INT_finish
8128.LOP_DOUBLE_TO_INT_isNaN:
8129    movl      $0,(rFP,%ecx,4)
8130    .if 0
8131    movl      $0,4(rFP,%ecx,4)
8132    .endif
8133    jmp       .LOP_DOUBLE_TO_INT_finish
8134
8135/* continuation for OP_DOUBLE_TO_LONG */
8136
8137
8138.LOP_DOUBLE_TO_LONG_continue:
8139    .if 1
8140    movl     $0x80000000,%eax
8141    xorl     4(rFP,%ecx,4),%eax
8142    orl      (rFP,%ecx,4),%eax
8143    .else
8144    cmpl     $0x80000000,(rFP,%ecx,4)
8145    .endif
8146    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result
8147
8148.LOP_DOUBLE_TO_LONG_finish:
8149    ADVANCE_PC(1)
8150    GOTO_NEXT
8151
8152.LOP_DOUBLE_TO_LONG_special_case:
8153    fnstsw   %ax
8154    sahf
8155    jp       .LOP_DOUBLE_TO_LONG_isNaN
8156    adcl     $-1,(rFP,%ecx,4)
8157    .if 1
8158    adcl     $-1,4(rFP,%ecx,4)
8159    .endif
8160   jmp       .LOP_DOUBLE_TO_LONG_finish
8161.LOP_DOUBLE_TO_LONG_isNaN:
8162    movl      $0,(rFP,%ecx,4)
8163    .if 1
8164    movl      $0,4(rFP,%ecx,4)
8165    .endif
8166    jmp       .LOP_DOUBLE_TO_LONG_finish
8167
8168/* continuation for OP_DIV_INT */
8169.LOP_DIV_INT_continue_div:
8170    cltd
8171    idivl   %ecx
8172.LOP_DIV_INT_finish_div:
8173    movzbl   rINST_HI,%ecx         # ecl<- AA
8174    SET_VREG(%eax,%ecx)
8175    UNSPILL(rPC)
8176    FETCH_INST_WORD(2)
8177    ADVANCE_PC(2)
8178    GOTO_NEXT
8179
8180/* continuation for OP_REM_INT */
8181.LOP_REM_INT_continue_div:
8182    cltd
8183    idivl   %ecx
8184.LOP_REM_INT_finish_div:
8185    movzbl   rINST_HI,%ecx         # ecl<- AA
8186    SET_VREG(%edx,%ecx)
8187    UNSPILL(rPC)
8188    FETCH_INST_WORD(2)
8189    ADVANCE_PC(2)
8190    GOTO_NEXT
8191
8192/* continuation for OP_MUL_LONG */
8193
8194.LOP_MUL_LONG_continue:
8195    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8196    movzbl    rINST_HI,%ecx       # ecx<- A
8197    movl      %edx,4(rFP,%ecx,4)  # v[B+1]<- %edx
8198    UNSPILL(rPC)                  # restore rPC/%edx
8199    FETCH_INST_WORD(2)
8200    UNSPILL(rIBASE)
8201    movl      %eax,(rFP,%ecx,4)   # v[B]<- %eax
8202    ADVANCE_PC(2)
8203    GOTO_NEXT
8204
8205/* continuation for OP_DIV_LONG */
8206
8207.LOP_DIV_LONG_continue:
8208    call     __divdi3
8209.LOP_DIV_LONG_finish:
8210    movzbl   rINST_HI,%ecx
8211    SET_VREG_WORD(rPC,%ecx,1)
8212    UNSPILL(rPC)
8213    SET_VREG_WORD(%eax,%ecx,0)
8214    FETCH_INST_WORD(2)
8215    ADVANCE_PC(2)
8216    GOTO_NEXT
8217
8218.LOP_DIV_LONG_check_zero:
8219    testl   rPC,rPC
8220    jne     .LOP_DIV_LONG_notSpecial
8221    UNSPILL(rPC)
8222    jmp     common_errDivideByZero
8223.LOP_DIV_LONG_check_neg1:
8224    testl   rPC,%eax
8225    jne     .LOP_DIV_LONG_notSpecial
8226    GET_VREG_WORD(rPC,%ecx,0)
8227    GET_VREG_WORD(%ecx,%ecx,1)
8228    testl    rPC,rPC
8229    jne      .LOP_DIV_LONG_notSpecial1
8230    cmpl     $0x80000000,%ecx
8231    jne      .LOP_DIV_LONG_notSpecial1
8232    /* minint / -1, return minint on div, 0 on rem */
8233    xorl     %eax,%eax
8234    movl     $0x80000000,%edx
8235    jmp      .LOP_DIV_LONG_finish
8236
8237/* continuation for OP_REM_LONG */
8238
8239.LOP_REM_LONG_continue:
8240    call     __moddi3
8241.LOP_REM_LONG_finish:
8242    movzbl   rINST_HI,%ecx
8243    SET_VREG_WORD(rPC,%ecx,1)
8244    UNSPILL(rPC)
8245    SET_VREG_WORD(%eax,%ecx,0)
8246    FETCH_INST_WORD(2)
8247    ADVANCE_PC(2)
8248    GOTO_NEXT
8249
8250.LOP_REM_LONG_check_zero:
8251    testl   rPC,rPC
8252    jne     .LOP_REM_LONG_notSpecial
8253    UNSPILL(rPC)
8254    jmp     common_errDivideByZero
8255.LOP_REM_LONG_check_neg1:
8256    testl   rPC,%eax
8257    jne     .LOP_REM_LONG_notSpecial
8258    GET_VREG_WORD(rPC,%ecx,0)
8259    GET_VREG_WORD(%ecx,%ecx,1)
8260    testl    rPC,rPC
8261    jne      .LOP_REM_LONG_notSpecial1
8262    cmpl     $0x80000000,%ecx
8263    jne      .LOP_REM_LONG_notSpecial1
8264    /* minint / -1, return minint on div, 0 on rem */
8265    xorl     %eax,%eax
8266    movl     $0,%edx
8267    jmp      .LOP_REM_LONG_finish
8268
8269/* continuation for OP_SHL_LONG */
8270
8271.LOP_SHL_LONG_finish:
8272    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- %eax
8273    ADVANCE_PC(2)
8274    GOTO_NEXT
8275
8276/* continuation for OP_SHR_LONG */
8277
8278
8279.LOP_SHR_LONG_finish:
8280    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- eax
8281    ADVANCE_PC(2)
8282    GOTO_NEXT
8283
8284/* continuation for OP_USHR_LONG */
8285
8286
8287.LOP_USHR_LONG_finish:
8288    SET_VREG_WORD(%eax,%ecx,0)        # v[BB+0]<- eax
8289    FETCH_INST_WORD(2)
8290    ADVANCE_PC(2)
8291    GOTO_NEXT
8292
8293/* continuation for OP_DIV_INT_2ADDR */
8294.LOP_DIV_INT_2ADDR_continue_div2addr:
8295    cltd
8296    idivl   %ecx
8297.LOP_DIV_INT_2ADDR_finish_div2addr:
8298    SET_VREG(%eax,rINST_FULL)
8299    UNSPILL(rPC)
8300    FETCH_INST_WORD(1)
8301    ADVANCE_PC(1)
8302    GOTO_NEXT
8303
8304/* continuation for OP_REM_INT_2ADDR */
8305.LOP_REM_INT_2ADDR_continue_div2addr:
8306    cltd
8307    idivl   %ecx
8308.LOP_REM_INT_2ADDR_finish_div2addr:
8309    SET_VREG(%edx,rINST_FULL)
8310    UNSPILL(rPC)
8311    FETCH_INST_WORD(1)
8312    ADVANCE_PC(1)
8313    GOTO_NEXT
8314
8315/* continuation for OP_MUL_LONG_2ADDR */
8316
8317.LOP_MUL_LONG_2ADDR_continue:
8318    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8319    movl      %edx,4(rIBASE)      # v[A+1]<- %edx
8320    UNSPILL(rPC)                  # restore rPC/%edx
8321    FETCH_INST_WORD(1)
8322    movl      %eax,(rIBASE)       # v[A]<- %eax
8323    UNSPILL(rFP)
8324    UNSPILL(rIBASE)
8325    ADVANCE_PC(1)
8326    GOTO_NEXT
8327
8328/* continuation for OP_DIV_LONG_2ADDR */
8329
8330.LOP_DIV_LONG_2ADDR_continue:
8331    movl     %eax,OUT_ARG3(%esp)
8332    movl     rPC,OUT_ARG0(%esp)
8333    movl     %ecx,OUT_ARG1(%esp)
8334    call     __divdi3
8335.LOP_DIV_LONG_2ADDR_finish:
8336    movl     rINST_FULL,%ecx
8337    SET_VREG_WORD(rPC,%ecx,1)
8338    UNSPILL(rPC)
8339    SET_VREG_WORD(%eax,%ecx,0)
8340    FETCH_INST_WORD(1)
8341    ADVANCE_PC(1)
8342    GOTO_NEXT
8343
8344.LOP_DIV_LONG_2ADDR_check_zero:
8345    testl   rPC,rPC
8346    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8347    UNSPILL(rPC)
8348    jmp     common_errDivideByZero
8349.LOP_DIV_LONG_2ADDR_check_neg1:
8350    testl   rPC,%eax
8351    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8352    GET_VREG_WORD(rPC,rINST_FULL,0)
8353    GET_VREG_WORD(%ecx,rINST_FULL,1)
8354    testl    rPC,rPC
8355    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8356    cmpl     $0x80000000,%ecx
8357    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8358    /* minint / -1, return minint on div, 0 on rem */
8359    xorl     %eax,%eax
8360    movl     $0x80000000,%edx
8361    jmp      .LOP_DIV_LONG_2ADDR_finish
8362
8363/* continuation for OP_REM_LONG_2ADDR */
8364
8365.LOP_REM_LONG_2ADDR_continue:
8366    movl     %eax,OUT_ARG3(%esp)
8367    movl     rPC,OUT_ARG0(%esp)
8368    movl     %ecx,OUT_ARG1(%esp)
8369    call     __moddi3
8370.LOP_REM_LONG_2ADDR_finish:
8371    movl     rINST_FULL,%ecx
8372    SET_VREG_WORD(rPC,%ecx,1)
8373    UNSPILL(rPC)
8374    SET_VREG_WORD(%eax,%ecx,0)
8375    FETCH_INST_WORD(1)
8376    ADVANCE_PC(1)
8377    GOTO_NEXT
8378
8379.LOP_REM_LONG_2ADDR_check_zero:
8380    testl   rPC,rPC
8381    jne     .LOP_REM_LONG_2ADDR_notSpecial
8382    UNSPILL(rPC)
8383    jmp     common_errDivideByZero
8384.LOP_REM_LONG_2ADDR_check_neg1:
8385    testl   rPC,%eax
8386    jne     .LOP_REM_LONG_2ADDR_notSpecial
8387    GET_VREG_WORD(rPC,rINST_FULL,0)
8388    GET_VREG_WORD(%ecx,rINST_FULL,1)
8389    testl    rPC,rPC
8390    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8391    cmpl     $0x80000000,%ecx
8392    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8393    /* minint / -1, return minint on div, 0 on rem */
8394    xorl     %eax,%eax
8395    movl     $0,%edx
8396    jmp      .LOP_REM_LONG_2ADDR_finish
8397
8398/* continuation for OP_SHL_LONG_2ADDR */
8399
8400
8401.LOP_SHL_LONG_2ADDR_finish:
8402    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8403    FETCH_INST_WORD(1)
8404    ADVANCE_PC(1)
8405    GOTO_NEXT
8406
8407/* continuation for OP_SHR_LONG_2ADDR */
8408
8409
8410.LOP_SHR_LONG_2ADDR_finish:
8411    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8412    FETCH_INST_WORD(1)
8413    ADVANCE_PC(1)
8414    GOTO_NEXT
8415
8416/* continuation for OP_USHR_LONG_2ADDR */
8417
8418
8419.LOP_USHR_LONG_2ADDR_finish:
8420    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[AA+0]<- eax
8421    FETCH_INST_WORD(1)
8422    ADVANCE_PC(1)
8423    GOTO_NEXT
8424
8425/* continuation for OP_DIV_INT_LIT16 */
8426.LOP_DIV_INT_LIT16_continue_div:
8427    cltd
8428    idivl   %ecx
8429.LOP_DIV_INT_LIT16_finish_div:
8430    SET_VREG(%eax,rINST_FULL)
8431    UNSPILL(rPC)
8432    FETCH_INST_WORD(2)
8433    ADVANCE_PC(2)
8434    GOTO_NEXT
8435
8436/* continuation for OP_REM_INT_LIT16 */
8437.LOP_REM_INT_LIT16_continue_div:
8438    cltd
8439    idivl   %ecx
8440.LOP_REM_INT_LIT16_finish_div:
8441    SET_VREG(%edx,rINST_FULL)
8442    UNSPILL(rPC)
8443    FETCH_INST_WORD(2)
8444    ADVANCE_PC(2)
8445    GOTO_NEXT
8446
8447/* continuation for OP_DIV_INT_LIT8 */
8448.LOP_DIV_INT_LIT8_continue_div:
8449    cltd
8450    idivl   %ecx
8451.LOP_DIV_INT_LIT8_finish_div:
8452    SET_VREG(%eax,rINST_FULL)
8453    UNSPILL(rPC)
8454    FETCH_INST_WORD(2)
8455    ADVANCE_PC(2)
8456    GOTO_NEXT
8457
8458/* continuation for OP_REM_INT_LIT8 */
8459.LOP_REM_INT_LIT8_continue_div:
8460    cltd
8461    idivl   %ecx
8462.LOP_REM_INT_LIT8_finish_div:
8463    SET_VREG(%edx,rINST_FULL)
8464    UNSPILL(rPC)
8465    FETCH_INST_WORD(2)
8466    ADVANCE_PC(2)
8467    GOTO_NEXT
8468
8469/* continuation for OP_IGET_VOLATILE */
8470
8471
8472.LOP_IGET_VOLATILE_resolve:
8473    EXPORT_PC()
8474    SPILL(rPC)
8475    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8476    UNSPILL(rIBASE)
8477    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8478    SPILL_TMP(%ecx)                               # save object pointer across call
8479    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8480    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8481    UNSPILL_TMP(%ecx)
8482    UNSPILL(rPC)
8483    testl   %eax,%eax                             #  ... which returns InstrField ptr
8484    jne     .LOP_IGET_VOLATILE_finish
8485    jmp     common_exceptionThrown
8486
8487.LOP_IGET_VOLATILE_finish:
8488    /*
8489     * Currently:
8490     *   eax holds resolved field
8491     *   ecx holds object
8492     *   rIBASE is scratch, but needs to be unspilled
8493     *   rINST_FULL holds A
8494     */
8495    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8496    UNSPILL(rIBASE)
8497    testl   %ecx,%ecx                            # object null?
8498    je      common_errNullObject                 # object was null
8499    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
8500    movl    rINST_FULL,%eax                      # eax<- A
8501    FETCH_INST_WORD(2)
8502    SET_VREG(%ecx,%eax)
8503    ADVANCE_PC(2)
8504    GOTO_NEXT
8505
8506/* continuation for OP_IPUT_VOLATILE */
8507
8508
8509.LOP_IPUT_VOLATILE_resolve:
8510    EXPORT_PC()
8511    SPILL(rPC)
8512    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8513    UNSPILL(rIBASE)
8514    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8515    SPILL_TMP(%ecx)                               # save object pointer across call
8516    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8517    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8518    UNSPILL_TMP(%ecx)
8519    UNSPILL(rPC)
8520    testl   %eax,%eax                             #  ... which returns InstrField ptr
8521    jne     .LOP_IPUT_VOLATILE_finish
8522    jmp     common_exceptionThrown
8523
8524.LOP_IPUT_VOLATILE_finish:
8525    /*
8526     * Currently:
8527     *   eax holds resolved field
8528     *   ecx holds object
8529     *   rIBASE is scratch, but needs to be unspilled
8530     *   rINST_FULL holds A
8531     */
8532    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
8533    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8534    UNSPILL(rIBASE)
8535    testl   %ecx,%ecx                            # object null?
8536    je      common_errNullObject                 # object was null
8537    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
8538    FETCH_INST_WORD(2)
8539    ADVANCE_PC(2)
8540    GOTO_NEXT
8541
8542/* continuation for OP_SGET_VOLATILE */
8543
8544    /*
8545     * Go resolve the field
8546     */
8547.LOP_SGET_VOLATILE_resolve:
8548    GET_GLUE(%ecx)
8549    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8550    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8551    EXPORT_PC()                                 # could throw, need to export
8552    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8553    SPILL(rPC)
8554    movl     %eax,OUT_ARG1(%esp)
8555    movl     %ecx,OUT_ARG0(%esp)
8556    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8557    UNSPILL(rPC)
8558    testl    %eax,%eax
8559    jne      .LOP_SGET_VOLATILE_finish                 # success, continue
8560    jmp      common_exceptionThrown             # no, handle exception
8561
8562/* continuation for OP_SPUT_VOLATILE */
8563
8564    /*
8565     * Go resolve the field
8566     */
8567.LOP_SPUT_VOLATILE_resolve:
8568    GET_GLUE(%ecx)
8569    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8570    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8571    EXPORT_PC()                                 # could throw, need to export
8572    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8573    SPILL(rPC)
8574    movl     %eax,OUT_ARG1(%esp)
8575    movl     %ecx,OUT_ARG0(%esp)
8576    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8577    UNSPILL(rPC)
8578    testl    %eax,%eax
8579    jne      .LOP_SPUT_VOLATILE_finish                 # success, continue
8580    jmp      common_exceptionThrown             # no, handle exception
8581
8582/* continuation for OP_IGET_OBJECT_VOLATILE */
8583
8584
8585.LOP_IGET_OBJECT_VOLATILE_resolve:
8586    EXPORT_PC()
8587    SPILL(rPC)
8588    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8589    UNSPILL(rIBASE)
8590    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8591    SPILL_TMP(%ecx)                               # save object pointer across call
8592    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8593    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8594    UNSPILL_TMP(%ecx)
8595    UNSPILL(rPC)
8596    testl   %eax,%eax                             #  ... which returns InstrField ptr
8597    jne     .LOP_IGET_OBJECT_VOLATILE_finish
8598    jmp     common_exceptionThrown
8599
8600.LOP_IGET_OBJECT_VOLATILE_finish:
8601    /*
8602     * Currently:
8603     *   eax holds resolved field
8604     *   ecx holds object
8605     *   rIBASE is scratch, but needs to be unspilled
8606     *   rINST_FULL holds A
8607     */
8608    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8609    UNSPILL(rIBASE)
8610    testl   %ecx,%ecx                            # object null?
8611    je      common_errNullObject                 # object was null
8612    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
8613    movl    rINST_FULL,%eax                      # eax<- A
8614    FETCH_INST_WORD(2)
8615    SET_VREG(%ecx,%eax)
8616    ADVANCE_PC(2)
8617    GOTO_NEXT
8618
8619/* continuation for OP_EXECUTE_INLINE */
8620
8621.LOP_EXECUTE_INLINE_continue:
8622    /*
8623     * Extract args, call function.
8624     *  ecx = #of args (0-4)
8625     *  eax = call index
8626     *  @esp = return addr
8627     *  esp is -4 from normal
8628     *
8629     *  Go ahead and load all 4 args, even if not used.
8630     */
8631    movzwl    4(rPC),rPC
8632
8633    movl      $0xf,%ecx
8634    andl      rPC,%ecx
8635    GET_VREG(%ecx,%ecx)
8636    sarl      $4,rPC
8637    movl      %ecx,4+OUT_ARG0(%esp)
8638
8639    movl      $0xf,%ecx
8640    andl      rPC,%ecx
8641    GET_VREG(%ecx,%ecx)
8642    sarl      $4,rPC
8643    movl      %ecx,4+OUT_ARG1(%esp)
8644
8645    movl      $0xf,%ecx
8646    andl      rPC,%ecx
8647    GET_VREG(%ecx,%ecx)
8648    sarl      $4,rPC
8649    movl      %ecx,4+OUT_ARG2(%esp)
8650
8651    movl      $0xf,%ecx
8652    andl      rPC,%ecx
8653    GET_VREG(%ecx,%ecx)
8654    sarl      $4,rPC
8655    movl      %ecx,4+OUT_ARG3(%esp)
8656
8657    sall      $4,%eax      # index *= sizeof(table entry)
8658    jmp       *gDvmInlineOpsTable(%eax)
8659    # will return to caller of .LOP_EXECUTE_INLINE_continue
8660
8661/* continuation for OP_IPUT_OBJECT_QUICK */
8662
8663.LOP_IPUT_OBJECT_QUICK_finish:
8664    testl     rINST_FULL,rINST_FULL         # did we store null?
8665    FETCH_INST_WORD(2)
8666    movl      offGlue_cardTable(%eax),%eax  # get card table base
8667    je        1f                            # skip card mark if null store
8668    shrl      $GC_CARD_SHIFT,%ecx          # object head to card number
8669    movb      %al,(%eax,%ecx)               # mark card
86701:
8671    ADVANCE_PC(2)
8672    GOTO_NEXT
8673
8674/* continuation for OP_IPUT_OBJECT_VOLATILE */
8675
8676
8677.LOP_IPUT_OBJECT_VOLATILE_resolve:
8678    EXPORT_PC()
8679    SPILL(rPC)
8680    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8681    UNSPILL(rIBASE)
8682    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8683    SPILL_TMP(%ecx)                               # save object pointer across call
8684    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8685    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8686    UNSPILL_TMP(%ecx)
8687    UNSPILL(rPC)
8688    testl   %eax,%eax                             #  ... which returns InstrField ptr
8689    jne     .LOP_IPUT_OBJECT_VOLATILE_finish
8690    jmp     common_exceptionThrown
8691
8692.LOP_IPUT_OBJECT_VOLATILE_finish:
8693    /*
8694     * Currently:
8695     *   eax holds resolved field
8696     *   ecx holds object
8697     *   rIBASE is scratch, but needs to be unspilled
8698     *   rINST_FULL holds A
8699     */
8700    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
8701    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8702    UNSPILL(rIBASE)
8703    testl   %ecx,%ecx                            # object null?
8704    je      common_errNullObject                 # object was null
8705    movl    rINST_FULL,(%ecx,%eax)          # obj.field <- v[A](8/16/32 bits)
8706    GET_GLUE(%eax)
8707    testl   rINST_FULL,rINST_FULL                # stored a NULL?
8708    movl    offGlue_cardTable(%eax),%eax         # get card table base
8709    FETCH_INST_WORD(2)
8710    je      1f                                   # skip card mark if null store
8711    shrl    $GC_CARD_SHIFT,%ecx                 # object head to card number
8712    movb    %al,(%eax,%ecx)                      # mark card
87131:
8714    ADVANCE_PC(2)
8715    GOTO_NEXT
8716
8717/* continuation for OP_SGET_OBJECT_VOLATILE */
8718
8719    /*
8720     * Go resolve the field
8721     */
8722.LOP_SGET_OBJECT_VOLATILE_resolve:
8723    GET_GLUE(%ecx)
8724    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8725    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8726    EXPORT_PC()                                 # could throw, need to export
8727    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8728    SPILL(rPC)
8729    movl     %eax,OUT_ARG1(%esp)
8730    movl     %ecx,OUT_ARG0(%esp)
8731    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8732    UNSPILL(rPC)
8733    testl    %eax,%eax
8734    jne      .LOP_SGET_OBJECT_VOLATILE_finish                 # success, continue
8735    jmp      common_exceptionThrown             # no, handle exception
8736
8737/* continuation for OP_SPUT_OBJECT_VOLATILE */
8738
8739
8740.LOP_SPUT_OBJECT_VOLATILE_continue:
8741    movl      %ecx,offStaticField_value(%eax)
8742    testl     %ecx,%ecx
8743    GET_GLUE(%ecx)
8744    FETCH_INST_WORD(2)
8745    je        1f
8746    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
8747    shrl      $GC_CARD_SHIFT,%eax               # head to card number
8748    movb      %cl,(%ecx,%eax)                    # mark card
87491:
8750    ADVANCE_PC(2)
8751    GOTO_NEXT
8752
8753.LOP_SPUT_OBJECT_VOLATILE_resolve:
8754    GET_GLUE(%ecx)
8755    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8756    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8757    EXPORT_PC()                                 # could throw, need to export
8758    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8759    SPILL(rPC)
8760    movl     %eax,OUT_ARG1(%esp)
8761    movl     %ecx,OUT_ARG0(%esp)
8762    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8763    UNSPILL(rPC)
8764    testl    %eax,%eax
8765    jne      .LOP_SPUT_OBJECT_VOLATILE_finish                 # success, continue
8766    jmp      common_exceptionThrown             # no, handle exception
8767
8768    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8769    .global dvmAsmSisterEnd
8770dvmAsmSisterEnd:
8771
8772/* File: x86/entry.S */
8773/*
8774 * Copyright (C) 2008 The Android Open Source Project
8775 *
8776 * Licensed under the Apache License, Version 2.0 (the "License");
8777 * you may not use this file except in compliance with the License.
8778 * You may obtain a copy of the License at
8779 *
8780 *      http://www.apache.org/licenses/LICENSE-2.0
8781 *
8782 * Unless required by applicable law or agreed to in writing, software
8783 * distributed under the License is distributed on an "AS IS" BASIS,
8784 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8785 * See the License for the specific language governing permissions and
8786 * limitations under the License.
8787 */
8788
8789
8790    .text
8791    .global dvmMterpStdRun
8792    .type   dvmMterpStdRun, %function
8793/*
8794 * bool dvmMterpStdRun(MterpGlue* glue)
8795 *
8796 * Interpreter entry point.  Returns changeInterp.
8797 *
8798 */
8799dvmMterpStdRun:
8800    push    %ebp
8801    movl    %esp,%ebp
8802    push    %edi
8803    push    %esi
8804    push    %ebx
8805
8806/* at this point, stack is misaligned by 1 word
8807   We're allocating spill space for 6 words, plus
8808   outgoing argument (5 words) and local variables
8809   (4 words) - 15 words or 60 bytes total. See
8810   diagram in header.S
8811*/
8812    subl   $60,%esp
8813
8814/* Set up "named" registers */
8815    movl    IN_ARG0(%ebp),%ecx
8816    movl    %ecx,rGLUE_SPILL(%ebp)
8817    LOAD_PC_FROM_GLUE(%ecx)
8818    LOAD_FP_FROM_GLUE(%ecx)
8819    movl    $dvmAsmInstructionStart,rIBASE
8820
8821/* Remember %esp for future "longjmp" */
8822    movl    %esp,offGlue_bailPtr(%ecx)
8823
8824/* How to start? */
8825    movb    offGlue_entryPoint(%ecx),%al
8826
8827/* Normal start? */
8828    cmpb    $kInterpEntryInstr,%al
8829    jne     .Lnot_instr
8830
8831   /* Normal case: start executing the instruction at rPC */
8832    FETCH_INST()
8833    GOTO_NEXT
8834
8835.Lnot_instr:
8836    /* Reset to normal case */
8837    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8838    cmpb   $kInterpEntryReturn,%al
8839    je     common_returnFromMethod
8840    cmpb   $kInterpEntryThrow,%al
8841    je     common_exceptionThrown
8842    movzx  %al,%eax
8843    movl   %eax,OUT_ARG1(%esp)
8844    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
8845    call   printf
8846    call   dvmAbort
8847    /* Not reached */
8848
8849
8850    .global dvmMterpStdBail
8851    .type   dvmMterpStdBail, %function
8852/*
8853 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8854 *
8855 * Restore the stack pointer and PC from the save point established on entry.
8856 * This is essentially the same as a longjmp, but should be cheaper.  The
8857 * last instruction causes us to return to whoever called dvmMterpStdRun.
8858 *
8859 * We're not going to build a standard frame here, so the arg accesses will
8860 * look a little strange.
8861 *
8862 * On entry:
8863 *  esp+4 (arg0)  MterpGlue* glue
8864 *  esp+8 (arg1)  bool changeInterp
8865 */
8866dvmMterpStdBail:
8867    movl    4(%esp),%ecx                 # grab glue
8868    movl    8(%esp),%eax                 # changeInterp to return reg
8869    movl    offGlue_bailPtr(%ecx),%esp   # Stack back to normal
8870    addl    $60,%esp                    # Strip dvmMterpStdRun's frame
8871    pop     %ebx
8872    pop     %esi
8873    pop     %edi
8874    pop     %ebp
8875    ret                                  # return to dvmMterpStdRun's caller
8876
8877
8878/*
8879 * Strings
8880 */
8881    .section    .rodata
8882.LstrBadEntryPoint:
8883    .asciz  "Bad entry point %d\n"
8884
8885/* File: x86/footer.S */
8886/*
8887 * Copyright (C) 2008 The Android Open Source Project
8888 *
8889 * Licensed under the Apache License, Version 2.0 (the "License");
8890 * you may not use this file except in compliance with the License.
8891 * You may obtain a copy of the License at
8892 *
8893 *      http://www.apache.org/licenses/LICENSE-2.0
8894 *
8895 * Unless required by applicable law or agreed to in writing, software
8896 * distributed under the License is distributed on an "AS IS" BASIS,
8897 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8898 * See the License for the specific language governing permissions and
8899 * limitations under the License.
8900 */
8901/*
8902 * Common subroutines and data.
8903 */
8904
8905/*
8906 * Common code when a backwards branch is taken
8907 *
8908 * On entry:
8909 *   ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
8910 */
8911common_backwardBranch:
8912    GET_GLUE(%ecx)
8913    call   common_periodicChecks  # Note: expects rPC to be preserved
8914    ADVANCE_PC_INDEXED(rINST_FULL)
8915    FETCH_INST()
8916    GOTO_NEXT
8917
8918
8919
8920/*
8921 * Common code for method invocation with range.
8922 *
8923 * On entry:
8924 *   eax = Method* methodToCall
8925 *   rINST trashed, must reload
8926 */
8927
8928common_invokeMethodRange:
8929.LinvokeNewRange:
8930
8931   /*
8932    * prepare to copy args to "outs" area of current frame
8933    */
8934
8935    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
8936    movzwl      4(rPC), %ecx            # %ecx<- CCCC
8937    SPILL(rPC)
8938    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
8939    test        rINST_FULL, rINST_FULL
8940    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
8941    jz          .LinvokeArgsDone        # no args; jump to args done
8942
8943
8944   /*
8945    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
8946    * (very few methods have > 10 args; could unroll for common cases)
8947    */
8948
8949    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
8950    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
8951    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
8952    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
8953    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
89541:
8955    movl        (%ecx), %ebx            # %ebx<- vCCCC
8956    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
8957    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
8958    movl        %ebx, (%edx)            # *outs<- vCCCC
8959    lea         4(%edx), %edx           # outs++
8960    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
8961    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
8962    jmp         .LinvokeArgsDone        # continue
8963
8964   /*
8965    * %eax is "Method* methodToCall", the method we're trying to call
8966    * prepare to copy args to "outs" area of current frame
8967    */
8968
8969common_invokeMethodNoRange:
8970.LinvokeNewNoRange:
8971    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
8972    SPILL(rPC)
8973    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
8974    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
8975    je          .LinvokeArgsDone        # no args; jump to args done
8976    movzwl      4(rPC), %ecx            # %ecx<- GFED
8977    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
8978
8979   /*
8980    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
8981    */
8982
8983.LinvokeNonRange:
8984    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
8985    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
8986    jl          1f                      # handle 1 arg
8987    je          2f                      # handle 2 args
8988    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
8989    jl          3f                      # handle 3 args
8990    je          4f                      # handle 4 args
89915:
8992    andl        $15, rINST_FULL        # rINST<- A
8993    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
8994    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
8995    movl        %ecx, (%edx)            # *outs<- vA
8996    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
89974:
8998    shr         $12, %ecx              # %ecx<- G
8999    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9000    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
9001    movl        %ecx, (%edx)            # *outs<- vG
9002    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90033:
9004    and         $0x0f00, %ecx          # %ecx<- 0F00
9005    shr         $8, %ecx               # %ecx<- F
9006    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9007    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
9008    movl        %ecx, (%edx)            # *outs<- vF
9009    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90102:
9011    and         $0x00f0, %ecx          # %ecx<- 00E0
9012    shr         $4, %ecx               # %ecx<- E
9013    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9014    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
9015    movl        %ecx, (%edx)            # *outs<- vE
9016    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90171:
9018    and         $0x000f, %ecx          # %ecx<- 000D
9019    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
9020    movl        %ecx, -4(%edx)          # *--outs<- vD
90210:
9022
9023   /*
9024    * %eax is "Method* methodToCall", the method we're trying to call
9025    * find space for the new stack frame, check for overflow
9026    */
9027
9028.LinvokeArgsDone:
9029    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
9030    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
9031    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
9032    shl         $2, %edx               # %edx<- update offset
9033    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
9034    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
9035    GET_GLUE(%edx)                      # %edx<- pMterpGlue
9036    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
9037    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
9038    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
9039    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
9040    shl         $2, %ecx               # %ecx<- update offset for outsSize
9041    movl        %eax, %edx              # %edx<- newSaveArea
9042    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
9043    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
9044    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
9045    jl          .LstackOverflow         # handle frame overflow
9046
9047   /*
9048    * set up newSaveArea
9049    */
9050
9051#ifdef EASY_GDB
9052    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
9053    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
9054#endif
9055    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
9056    movl        rPC_SPILL(%ebp), %ecx
9057    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
9058    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
9059    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
9060    jne         .LinvokeNative          # handle native call
9061
9062   /*
9063    * Update "glue" values for the new method
9064    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
9065    */
9066
9067    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
9068    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
9069    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
9070    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
9071    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
9072    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
9073    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
9074    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
9075    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
9076    FETCH_INST()
9077    GOTO_NEXT                           # jump to methodToCall->insns
9078
9079   /*
9080    * Prep for the native call
9081    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
9082    */
9083
9084.LinvokeNative:
9085    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
9086    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9087    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
9088    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
9089    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
9090    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
9091    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
9092    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
9093    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
9094    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
9095    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
9096    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
9097    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
9098    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
9099    push        %edx                    # push parameter newFP
9100
9101    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
9102    lea         4(%esp), %esp
9103    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
9104    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
9105    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
9106    cmp         $0, offThread_exception(%eax) # check for exception
9107    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
9108    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
9109    UNSPILL(rPC)
9110    jne         common_exceptionThrown  # handle exception
9111    FETCH_INST_WORD(3)
9112    ADVANCE_PC(3)
9113    GOTO_NEXT                           # jump to next instruction
9114
9115.LstackOverflow:    # eax=methodToCall
9116    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9117    GET_GLUE(%eax)                      # %eax<- pMterpGlue
9118    movl        offGlue_self(%eax), %eax # %eax<- glue->self
9119    movl        %eax, OUT_ARG0(%esp)    # push parameter self
9120    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
9121    UNSPILL(rPC)                        # return: void
9122    jmp         common_exceptionThrown  # handle exception
9123
9124
9125/*
9126 * Common invoke code (old-style).
9127 * TUNING:  Rewrite along lines of new armv5 code?
9128 *
9129 * On entry:
9130 *   eax = Method* methodToCall
9131 *   ecx = bool methodCallRange
9132 *   rINST trashed, must reload
9133 */
9134common_invokeOld:
9135    movl     %ecx,OUT_ARG1(%esp)     # arg1<- methodCallRange
9136    GET_GLUE(%ecx)
9137    movzwl  (rPC),rINST_FULL         # recover rINST
9138    movl     %eax,OUT_ARG2(%esp)     # arg2<- method
9139    movzwl   4(rPC),%eax             # eax<- GFED or CCCC
9140    SAVE_PC_TO_GLUE(%ecx)
9141    SAVE_FP_TO_GLUE(%ecx)
9142    movzbl   rINST_HI,rINST_FULL
9143    movl     rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
9144    movl     %ecx,OUT_ARG0(%esp)     # arg0<- GLUE
9145    movl     %eax,OUT_ARG4(%esp)     # arg4<- GFED/CCCC
9146    call     dvmMterp_invokeMethod
9147    jmp      common_resumeAfterGlueCall
9148
9149
9150/*
9151 * Do we need the thread to be suspended or have debugger/profiling activity?
9152 *
9153 * On entry:
9154 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
9155 *   ecx  -> GLUE pointer
9156 *
9157 * Note: A call will normally kill %eax, rPC/%edx and %ecx.  To
9158 *       streamline the normal case, this routine will preserve rPC and
9159 *       %ecx in addition to the normal caller save regs.  The save/restore
9160 *       is a bit ugly, but will happen in the relatively uncommon path.
9161 * TUNING: Might be worthwhile to inline this.
9162 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
9163 *       the suspendCount check so we can get both in 1 shot.
9164 * TODO: to match the other intepreters, this should handle suspension
9165 *       and then check for debugger/profiling after dvmCheckSuspendPending
9166 *       returns.
9167 */
9168common_periodicChecks:
9169    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
9170    cmpl    $0,(%eax)
9171    jne     1f
9172
9173#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9174#if defined(WITH_DEBUGGER)
9175    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
9176#endif
9177#if defined(WITH_PROFILER)
9178    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
9179#endif
9180#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9181    # TODO: check for NULL before load
9182    movzbl (%eax),%eax             # eax <- debuggerActive (boolean)
9183    orl    (%ecx),%eax             # eax <- debuggerActive || activeProfilers
9184#elif defined(WITH_DEBUGGER)
9185    # TODO: check for NULL before load
9186    movzbl (%eax),%eax             # eax <- debuggerActive (boolean)
9187#elif defined(WITH_PROFILER)
9188    movl   (%ecx),%eax             # eax <= activeProfilers
9189#endif
9190    GET_GLUE(%ecx)                 # restore rGLUE
9191    testl  %eax,%eax
9192    jne    3f                      # one or both active - switch interp
9193#endif
9194
9195    ret
9196
9197    /* Check for suspend */
91981:
9199    /*  At this point, the return pointer to the caller of
9200     *  common_periodicChecks is on the top of stack.  We need to preserve
9201     *  rPC(edx) and GLUE(ecx).  We'll spill rPC, and reload GLUE.
9202     *  The outgoing profile is:
9203     *      bool dvmCheckSuspendPending(Thread* self)
9204     *  Because we reached here via a call, go ahead and build a new frame.
9205     */
9206    EXPORT_PC()                         # need for precise GC
9207    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
9208    SPILL(rPC)                      # save edx
9209    push    %ebp
9210    movl    %esp,%ebp
9211    subl    $24,%esp
9212    movl    %eax,OUT_ARG0(%esp)
9213    call    dvmCheckSuspendPending
9214    addl    $24,%esp
9215    pop     %ebp
9216    UNSPILL(rPC)
9217    GET_GLUE(%ecx)
9218    ret
9219
9220    /* Switch interpreters */
9221    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
9222     * "complete" the interpretation of backwards branches.  In effect, we
9223     * are completing the interpretation of the branch instruction here,
9224     * and the new interpreter will resume interpretation at the branch
9225     * target. However, a switch request recognized during the handling
9226     * of a return from method instruction results in an immediate abort,
9227     * and the new interpreter will resume by re-interpreting the return
9228     * instruction.
9229     */
92303:
9231    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
9232    GET_GLUE(%ecx)                 # bail expect GLUE already loaded
9233    movl    $1,rINST_FULL         # set changeInterp to true
9234    jmp     common_gotoBail
9235
9236
9237/*
9238 * Common code for handling a return instruction
9239 */
9240common_returnFromMethod:
9241    GET_GLUE(%ecx)
9242    /* Set entry mode in case we bail */
9243    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
9244    xorl    rINST_FULL,rINST_FULL   # zero offset in case we switch interps
9245    call    common_periodicChecks   # Note: expects %ecx to be preserved
9246
9247    SAVEAREA_FROM_FP(%eax,rFP)                    # eax<- saveArea (old)
9248    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
9249    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
9250    cmpl    $0,rINST_FULL                        # break?
9251    je      common_gotoBail    # break frame, bail out completely
9252
9253    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
9254    movl    offGlue_self(%ecx),%eax               # eax<- self
9255    movl    rINST_FULL,offGlue_method(%ecx)  # glue->method = newSave->meethod
9256    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
9257    movl    offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
9258    FETCH_INST_WORD(3)
9259    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
9260    ADVANCE_PC(3)
9261    movl    %eax,offGlue_methodClassDex(%ecx)
9262    /* not bailing - restore entry mode to default */
9263    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
9264    GOTO_NEXT
9265
9266/*
9267 * Prepare to strip the current frame and "longjump" back to caller of
9268 * dvmMterpStdRun.
9269 *
9270 * on entry:
9271 *    rINST_FULL holds changeInterp
9272 *    ecx holds glue pointer
9273 *
9274 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
9275 */
9276common_gotoBail:
9277    SAVE_PC_TO_GLUE(%ecx)                # export state to glue
9278    SAVE_FP_TO_GLUE(%ecx)
9279    movl   %ecx,OUT_ARG0(%esp)           # glue in arg0
9280    movl   rINST_FULL,OUT_ARG1(%esp)     # changeInterp in arg1
9281    call    dvmMterpStdBail              # bail out....
9282
9283
9284/*
9285 * After returning from a "glued" function, pull out the updated values
9286 * and start executing at the next instruction.
9287 */
9288 common_resumeAfterGlueCall:
9289     GET_GLUE(%ecx)
9290     LOAD_PC_FROM_GLUE(%ecx)
9291     LOAD_FP_FROM_GLUE(%ecx)
9292     FETCH_INST()
9293     GOTO_NEXT
9294
9295/*
9296 * Integer divide or mod by zero
9297 */
9298common_errDivideByZero:
9299    EXPORT_PC()
9300    movl    $.LstrArithmeticException,%eax
9301    movl    %eax,OUT_ARG0(%esp)
9302    movl    $.LstrDivideByZero,%eax
9303    movl    %eax,OUT_ARG1(%esp)
9304    SPILL(rPC)
9305    call    dvmThrowException
9306    UNSPILL(rPC)
9307    jmp     common_exceptionThrown
9308
9309/*
9310 * Attempt to allocate an array with a negative size.
9311 */
9312common_errNegativeArraySize:
9313    EXPORT_PC()
9314    movl    $.LstrNegativeArraySizeException,%eax
9315    movl    %eax,OUT_ARG0(%esp)
9316    xorl    %eax,%eax
9317    movl    %eax,OUT_ARG1(%esp)
9318    SPILL(rPC)
9319    call    dvmThrowException
9320    UNSPILL(rPC)
9321    jmp     common_exceptionThrown
9322
9323/*
9324 * Attempt to allocate an array with a negative size.
9325 */
9326common_errNoSuchMethod:
9327
9328    EXPORT_PC()
9329    movl    $.LstrNoSuchMethodError,%eax
9330    movl    %eax,OUT_ARG0(%esp)
9331    xorl    %eax,%eax
9332    movl    %eax,OUT_ARG1(%esp)
9333    SPILL(rPC)
9334    call    dvmThrowException
9335    UNSPILL(rPC)
9336    jmp     common_exceptionThrown
9337
9338/*
9339 * Hit a null object when we weren't expecting one.  Export the PC, throw a
9340 * NullPointerException and goto the exception processing code.
9341 */
9342common_errNullObject:
9343    EXPORT_PC()
9344    movl    $.LstrNullPointerException,%eax
9345    movl    %eax,OUT_ARG0(%esp)
9346    xorl    %eax,%eax
9347    movl    %eax,OUT_ARG1(%esp)
9348    SPILL(rPC)
9349    call    dvmThrowException
9350    UNSPILL(rPC)
9351    jmp     common_exceptionThrown
9352
9353/*
9354 * Array index exceeds max.
9355 */
9356common_errArrayIndex:
9357    EXPORT_PC()
9358    movl    $.LstrArrayIndexException,%eax
9359    movl    %eax,OUT_ARG0(%esp)
9360    xorl    %eax,%eax
9361    movl    %eax,OUT_ARG1(%esp)
9362    SPILL(rPC)
9363    call    dvmThrowException
9364    UNSPILL(rPC)
9365    jmp     common_exceptionThrown
9366/*
9367 * Invalid array value.
9368 */
9369common_errArrayStore:
9370    EXPORT_PC()
9371    movl    $.LstrArrayStoreException,%eax
9372    movl    %eax,OUT_ARG0(%esp)
9373    xorl    %eax,%eax
9374    movl    %eax,OUT_ARG1(%esp)
9375    SPILL(rPC)
9376    call    dvmThrowException
9377    UNSPILL(rPC)
9378    jmp     common_exceptionThrown
9379
9380/*
9381 * Somebody has thrown an exception.  Handle it.
9382 *
9383 * If the exception processing code returns to us (instead of falling
9384 * out of the interpreter), continue with whatever the next instruction
9385 * now happens to be.
9386 *
9387 * This does not return.
9388 */
9389common_exceptionThrown:
9390    GET_GLUE(%ecx)
9391    SAVE_PC_TO_GLUE(%ecx)
9392    SAVE_FP_TO_GLUE(%ecx)
9393    movl    %ecx,OUT_ARG0(%esp)
9394    call    dvmMterp_exceptionThrown
9395    jmp     common_resumeAfterGlueCall
9396
9397common_abort:
9398    movl    $0xdeadf00d,%eax
9399    call     *%eax
9400
9401
9402/*
9403 * Strings
9404 */
9405
9406    .section     .rodata
9407.LstrNullPointerException:
9408    .asciz    "Ljava/lang/NullPointerException;"
9409.LstrArithmeticException:
9410    .asciz  "Ljava/lang/ArithmeticException;"
9411.LstrDivideByZero:
9412    .asciz  "divide by zero"
9413.LstrArrayIndexException:
9414    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9415.LstrArrayStoreException:
9416    .asciz  "Ljava/lang/ArrayStoreException;"
9417.LstrNegativeArraySizeException:
9418    .asciz  "Ljava/lang/NegativeArraySizeException;"
9419.LstrInstantiationError:
9420    .asciz  "Ljava/lang/InstantiationError;"
9421.LstrClassCastException:
9422    .asciz  "Ljava/lang/ClassCastException;"
9423.LstrNoSuchMethodError:
9424    .asciz  "Ljava/lang/NoSuchMethodError;"
9425.LstrInternalError:
9426    .asciz  "Ljava/lang/InternalError;"
9427.LstrFilledNewArrayNotImpl:
9428    .asciz  "filled-new-array only implemented for 'int'"
9429
9430