InterpAsm-x86.S revision 7520ee7ff226e12e06818561b15741d2575072e3
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_RETURN_VOID_BARRIER: /* 0xf1 */
5959    /* (stub) */
5960    GET_GLUE(%ecx)
5961    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5962    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5963    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5964    call      dvmMterp_OP_RETURN_VOID_BARRIER     # do the real work
5965    GET_GLUE(%ecx)
5966    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5967    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5968    FETCH_INST()
5969    GOTO_NEXT
5970/* ------------------------------ */
5971    .balign 64
5972.L_OP_IGET_QUICK: /* 0xf2 */
5973/* File: x86/OP_IGET_QUICK.S */
5974    /* For: iget-quick, iget-object-quick */
5975    /* op vA, vB, offset@CCCC */
5976    movzbl    rINST_HI,%ecx             # ecx<- BA
5977    sarl      $4,%ecx                  # ecx<- B
5978    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5979    movzwl    2(rPC),%eax               # eax<- field byte offset
5980    cmpl      $0,%ecx                  # is object null?
5981    je        common_errNullObject
5982    movl      (%ecx,%eax,1),%eax
5983    movzbl    rINST_HI,%ecx
5984    FETCH_INST_WORD(2)
5985    ADVANCE_PC(2)
5986    andb      $0xf,%cl                 # rINST_FULL<- A
5987    SET_VREG  (%eax,%ecx)               # fp[A]<- result
5988    GOTO_NEXT
5989
5990/* ------------------------------ */
5991    .balign 64
5992.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
5993/* File: x86/OP_IGET_WIDE_QUICK.S */
5994    /* For: iget-wide-quick */
5995    /* op vA, vB, offset@CCCC */
5996    movzbl    rINST_HI,%ecx             # ecx<- BA
5997    sarl      $4,%ecx                  # ecx<- B
5998    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5999    movzwl    2(rPC),%eax               # eax<- field byte offset
6000    cmpl      $0,%ecx                  # is object null?
6001    je        common_errNullObject
6002    leal      (%ecx,%eax,1),%eax        # eax<- address of 64-bit source
6003    movl      (%eax),%ecx               # ecx<- lsw
6004    movl      4(%eax),%eax               # eax<- msw
6005    movzbl    rINST_HI,rINST_FULL
6006    andb      $0xf,rINST_LO            # rINST_FULL<- A
6007    SET_VREG_WORD(%ecx,rINST_FULL,0)    # v[A+0]<- lsw
6008    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[A+1]<- msw
6009    FETCH_INST_WORD(2)
6010    ADVANCE_PC(2)
6011    GOTO_NEXT
6012
6013/* ------------------------------ */
6014    .balign 64
6015.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
6016/* File: x86/OP_IGET_OBJECT_QUICK.S */
6017/* File: x86/OP_IGET_QUICK.S */
6018    /* For: iget-quick, iget-object-quick */
6019    /* op vA, vB, offset@CCCC */
6020    movzbl    rINST_HI,%ecx             # ecx<- BA
6021    sarl      $4,%ecx                  # ecx<- B
6022    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
6023    movzwl    2(rPC),%eax               # eax<- field byte offset
6024    cmpl      $0,%ecx                  # is object null?
6025    je        common_errNullObject
6026    movl      (%ecx,%eax,1),%eax
6027    movzbl    rINST_HI,%ecx
6028    FETCH_INST_WORD(2)
6029    ADVANCE_PC(2)
6030    andb      $0xf,%cl                 # rINST_FULL<- A
6031    SET_VREG  (%eax,%ecx)               # fp[A]<- result
6032    GOTO_NEXT
6033
6034
6035/* ------------------------------ */
6036    .balign 64
6037.L_OP_IPUT_QUICK: /* 0xf5 */
6038/* File: x86/OP_IPUT_QUICK.S */
6039    /* For: iput-quick */
6040    /* op vA, vB, offset@CCCC */
6041    movzbl    rINST_HI,%ecx             # ecx<- BA
6042    sarl      $4,%ecx                  # ecx<- B
6043    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
6044    movzbl    rINST_HI,rINST_FULL
6045    andb      $0xf,rINST_LO            # rINST_FULL<- A
6046    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- v[A]
6047    movzwl    2(rPC),%eax               # eax<- field byte offset
6048    testl     %ecx,%ecx                  # is object null?
6049    je        common_errNullObject
6050    movl      rINST_FULL,(%ecx,%eax,1)
6051    FETCH_INST_WORD(2)
6052    ADVANCE_PC(2)
6053    GOTO_NEXT
6054
6055/* ------------------------------ */
6056    .balign 64
6057.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
6058/* File: x86/OP_IPUT_WIDE_QUICK.S */
6059    /* For: iput-wide-quick */
6060    /* op vA, vB, offset@CCCC */
6061    movzbl    rINST_HI,%ecx             # ecx<- BA
6062    sarl      $4,%ecx                  # ecx<- B
6063    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
6064    movzwl    2(rPC),%eax               # eax<- field byte offset
6065    testl      %ecx,%ecx                # is object null?
6066    je        common_errNullObject
6067    leal      (%ecx,%eax,1),%ecx        # ecx<- Address of 64-bit target
6068    movzbl    rINST_HI,rINST_FULL
6069    andb      $0xf,rINST_LO            # rINST_FULL<- A
6070    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- lsw
6071    GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
6072    movl      %eax,(%ecx)
6073    movl      rINST_FULL,4(%ecx)
6074    FETCH_INST_WORD(2)
6075    ADVANCE_PC(2)
6076    GOTO_NEXT
6077
6078/* ------------------------------ */
6079    .balign 64
6080.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
6081/* File: x86/OP_IPUT_OBJECT_QUICK.S */
6082    /* For: iput-object-quick */
6083    /* op vA, vB, offset@CCCC */
6084    movzbl    rINST_HI,%ecx             # ecx<- BA
6085    sarl      $4,%ecx                  # ecx<- B
6086    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
6087    movzbl    rINST_HI,rINST_FULL
6088    andb      $0xf,rINST_LO            # rINST_FULL<- A
6089    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- v[A]
6090    movzwl    2(rPC),%eax               # eax<- field byte offset
6091    testl     %ecx,%ecx                 # is object null?
6092    je        common_errNullObject
6093    movl      rINST_FULL,(%ecx,%eax,1)
6094    GET_GLUE(%eax)
6095    jmp       .LOP_IPUT_OBJECT_QUICK_finish
6096
6097/* ------------------------------ */
6098    .balign 64
6099.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
6100/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6101    /*
6102     * Handle an optimized virtual method call.
6103     *
6104     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6105     */
6106    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6107    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6108    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
6109    movzwl    2(rPC),%ecx               # ecx<- BBBB
6110    .if     (!0)
6111    andl      $0xf,%eax                # eax<- C (or stays CCCC)
6112    .endif
6113    GET_VREG(%eax,%eax)                 # eax<- vC ("this" ptr)
6114    testl     %eax,%eax                 # null?
6115    je        common_errNullObject      # yep, throw exception
6116    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6117    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6118    EXPORT_PC()                         # might throw later - get ready
6119    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
6120    jmp       common_invokeMethodNoRange
6121
6122/* ------------------------------ */
6123    .balign 64
6124.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
6125/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
6126/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6127    /*
6128     * Handle an optimized virtual method call.
6129     *
6130     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6131     */
6132    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6133    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6134    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
6135    movzwl    2(rPC),%ecx               # ecx<- BBBB
6136    .if     (!1)
6137    andl      $0xf,%eax                # eax<- C (or stays CCCC)
6138    .endif
6139    GET_VREG(%eax,%eax)                 # eax<- vC ("this" ptr)
6140    testl     %eax,%eax                 # null?
6141    je        common_errNullObject      # yep, throw exception
6142    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6143    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6144    EXPORT_PC()                         # might throw later - get ready
6145    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
6146    jmp       common_invokeMethodRange
6147
6148
6149/* ------------------------------ */
6150    .balign 64
6151.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
6152/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6153    /*
6154     * Handle an optimized "super" method call.
6155     *
6156     * for: [opt] invoke-super-quick, invoke-super-quick/range
6157     */
6158    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6159    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6160    GET_GLUE(%ecx)
6161    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
6162    movl      offGlue_method(%ecx),%ecx # ecx<- current method
6163    .if       (!0)
6164    andl      $0xf,%eax                # eax<- D (or stays CCCC)
6165    .endif
6166    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6167    GET_VREG(%eax,%eax)                 # eax<- "this"
6168    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6169    testl     %eax,%eax                 # null "this"?
6170    je        common_errNullObject      # "this" is null, throw exception
6171    movzwl    2(rPC),%eax               # eax<- BBBB
6172    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6173    EXPORT_PC()
6174    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
6175    jmp       common_invokeMethodNoRange
6176
6177/* ------------------------------ */
6178    .balign 64
6179.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
6180/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
6181/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6182    /*
6183     * Handle an optimized "super" method call.
6184     *
6185     * for: [opt] invoke-super-quick, invoke-super-quick/range
6186     */
6187    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6188    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6189    GET_GLUE(%ecx)
6190    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
6191    movl      offGlue_method(%ecx),%ecx # ecx<- current method
6192    .if       (!1)
6193    andl      $0xf,%eax                # eax<- D (or stays CCCC)
6194    .endif
6195    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6196    GET_VREG(%eax,%eax)                 # eax<- "this"
6197    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6198    testl     %eax,%eax                 # null "this"?
6199    je        common_errNullObject      # "this" is null, throw exception
6200    movzwl    2(rPC),%eax               # eax<- BBBB
6201    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6202    EXPORT_PC()
6203    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
6204    jmp       common_invokeMethodRange
6205
6206
6207/* ------------------------------ */
6208    .balign 64
6209.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
6210/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */
6211/* File: x86/OP_IPUT_OBJECT.S */
6212    /*
6213     * Object field put.
6214     *
6215     * for: iput-object
6216     */
6217    /* op vA, vB, field@CCCC */
6218    GET_GLUE(%ecx)
6219    SPILL(rIBASE)                                 # need another reg
6220    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
6221    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
6222    movzbl  rINST_HI,%ecx                         # ecx<- BA
6223    sarl    $4,%ecx                              # ecx<- B
6224    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
6225    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
6226    andb    $0xf,rINST_LO                        # rINST_FULL<- A
6227    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
6228    movl    (%eax,rIBASE,4),%eax                  # resolved entry
6229    testl   %eax,%eax                             # is resolved entry null?
6230    jne     .LOP_IPUT_OBJECT_VOLATILE_finish                    # no, already resolved
6231    movl    rIBASE,OUT_ARG1(%esp)
6232    GET_GLUE(rIBASE)
6233    jmp     .LOP_IPUT_OBJECT_VOLATILE_resolve
6234
6235
6236/* ------------------------------ */
6237    .balign 64
6238.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
6239/* File: x86/OP_SGET_OBJECT_VOLATILE.S */
6240/* File: x86/OP_SGET.S */
6241    /*
6242     * General 32-bit SGET handler.
6243     *
6244     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
6245     */
6246    /* op vAA, field@BBBB */
6247    GET_GLUE(%ecx)
6248    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
6249    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
6250    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
6251    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
6252    testl     %eax,%eax                          # resolved entry null?
6253    je        .LOP_SGET_OBJECT_VOLATILE_resolve                # if not, make it so
6254.LOP_SGET_OBJECT_VOLATILE_finish:     # field ptr in eax
6255    movl      offStaticField_value(%eax),%eax
6256    movzbl    rINST_HI,%ecx                      # ecx<- AA
6257    FETCH_INST_WORD(2)
6258    ADVANCE_PC(2)
6259    SET_VREG(%eax,%ecx)
6260    GOTO_NEXT
6261
6262
6263/* ------------------------------ */
6264    .balign 64
6265.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
6266/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */
6267/* File: x86/OP_SPUT_OBJECT.S */
6268    /*
6269     * SPUT object handler.
6270     */
6271    /* op vAA, field@BBBB */
6272    GET_GLUE(%ecx)
6273    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
6274    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
6275    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
6276    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField
6277    testl     %eax,%eax                          # resolved entry null?
6278    je        .LOP_SPUT_OBJECT_VOLATILE_resolve                # if not, make it so
6279.LOP_SPUT_OBJECT_VOLATILE_finish:     # field ptr in eax
6280    movzbl    rINST_HI,%ecx                      # ecx<- AA
6281    GET_VREG(%ecx,%ecx)
6282    jmp       .LOP_SPUT_OBJECT_VOLATILE_continue
6283
6284
6285/* ------------------------------ */
6286    .balign 64
6287.L_OP_UNUSED_FF: /* 0xff */
6288/* File: x86/OP_UNUSED_FF.S */
6289/* File: x86/unused.S */
6290    jmp     common_abort
6291
6292
6293
6294    .balign 64
6295    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
6296    .global dvmAsmInstructionEnd
6297dvmAsmInstructionEnd:
6298
6299/*
6300 * ===========================================================================
6301 *  Sister implementations
6302 * ===========================================================================
6303 */
6304    .global dvmAsmSisterStart
6305    .type   dvmAsmSisterStart, %function
6306    .text
6307    .balign 4
6308dvmAsmSisterStart:
6309
6310/* continuation for OP_CONST_STRING */
6311
6312/* This is the less common path, so we'll redo some work
6313   here rather than force spills on the common path */
6314.LOP_CONST_STRING_resolve:
6315    GET_GLUE(%eax)
6316    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
6317    EXPORT_PC()
6318    movl     offGlue_method(%eax),%eax # eax<- glue->method
6319    movzwl   2(rPC),%ecx               # ecx<- BBBB
6320    movl     offMethod_clazz(%eax),%eax
6321    SPILL(rPC)
6322    movl     %ecx,OUT_ARG1(%esp)
6323    movl     %eax,OUT_ARG0(%esp)
6324    call     dvmResolveString          # go resolve
6325    UNSPILL(rPC)
6326    testl    %eax,%eax                 # failed?
6327    je       common_exceptionThrown
6328    SET_VREG(%eax,rINST_FULL)
6329    FETCH_INST_WORD(2)
6330    ADVANCE_PC(2)
6331    GOTO_NEXT
6332
6333/* continuation for OP_CONST_STRING_JUMBO */
6334
6335/* This is the less common path, so we'll redo some work
6336   here rather than force spills on the common path */
6337.LOP_CONST_STRING_JUMBO_resolve:
6338    GET_GLUE(%eax)
6339    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
6340    EXPORT_PC()
6341    movl     offGlue_method(%eax),%eax # eax<- glue->method
6342    movl     2(rPC),%ecx               # ecx<- BBBBBBBB
6343    movl     offMethod_clazz(%eax),%eax
6344    SPILL(rPC)
6345    movl     %ecx,OUT_ARG1(%esp)
6346    movl     %eax,OUT_ARG0(%esp)
6347    call     dvmResolveString          # go resolve
6348    UNSPILL(rPC)
6349    testl    %eax,%eax                 # failed?
6350    je       common_exceptionThrown
6351    SET_VREG(%eax,rINST_FULL)
6352    FETCH_INST_WORD(3)
6353    ADVANCE_PC(3)
6354    GOTO_NEXT
6355
6356/* continuation for OP_CONST_CLASS */
6357
6358/* This is the less common path, so we'll redo some work
6359   here rather than force spills on the common path */
6360.LOP_CONST_CLASS_resolve:
6361    GET_GLUE(%eax)
6362    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
6363    EXPORT_PC()
6364    movl     offGlue_method(%eax),%eax # eax<- glue->method
6365    movl     $1,OUT_ARG2(%esp)        # true
6366    movzwl   2(rPC),%ecx               # ecx<- BBBB
6367    movl     offMethod_clazz(%eax),%eax
6368    SPILL(rPC)
6369    movl     %ecx,OUT_ARG1(%esp)
6370    movl     %eax,OUT_ARG0(%esp)
6371    call     dvmResolveClass           # go resolve
6372    UNSPILL(rPC)
6373    testl    %eax,%eax                 # failed?
6374    je       common_exceptionThrown
6375    SET_VREG(%eax,rINST_FULL)
6376    FETCH_INST_WORD(2)
6377    ADVANCE_PC(2)
6378    GOTO_NEXT
6379
6380/* continuation for OP_MONITOR_ENTER */
6381
6382.LOP_MONITOR_ENTER_continue:
6383    SPILL(rPC)                          # have to - caller save
6384    movl    %ecx,OUT_ARG0(%esp)
6385    movl    %eax,OUT_ARG1(%esp)
6386    call    dvmLockObject               # dvmLockObject(self,object)
6387    UNSPILL(rPC)
6388#ifdef WITH_DEADLOCK_PREDICTION
6389    GET_GLUE(%ecx)
6390    movl    offGlueSelf(%ecx),%ecx      # ecx<- glue->self
6391    movl    offThread_exception(%ecx),%eax
6392    testl   %eax,%eax
6393    jne     common_exceptionThrown
6394#endif
6395    ADVANCE_PC(1)
6396    GOTO_NEXT
6397
6398/* continuation for OP_MONITOR_EXIT */
6399
6400.LOP_MONITOR_EXIT_continue:
6401    call    dvmUnlockObject             # unlock(self,obj)
6402    UNSPILL(rPC)
6403    FETCH_INST_WORD(1)
6404    testl   %eax,%eax                   # success?
6405    ADVANCE_PC(1)
6406    je      common_exceptionThrown      # no, exception pending
6407    GOTO_NEXT
6408.LOP_MONITOR_EXIT_errNullObject:
6409    ADVANCE_PC(1)                       # advance before throw
6410    jmp     common_errNullObject
6411
6412/* continuation for OP_CHECK_CAST */
6413
6414    /*
6415     * Trivial test failed, need to perform full check.  This is common.
6416     *  ecx holds obj->clazz
6417     *  eax holds class resolved from BBBB
6418     *  rINST_FULL holds object
6419     */
6420.LOP_CHECK_CAST_fullcheck:
6421    movl    %eax,OUT_ARG1(%esp)
6422    movl    %ecx,OUT_ARG0(%esp)
6423    SPILL(rPC)
6424    call    dvmInstanceofNonTrivial     # eax<- boolean result
6425    UNSPILL(rPC)
6426    testl   %eax,%eax                   # failed?
6427    jne     .LOP_CHECK_CAST_okay            # no, success
6428
6429    # A cast has failed.  We need to throw a ClassCastException with the
6430    # class of the object that failed to be cast.
6431    EXPORT_PC()
6432    movl    offObject_clazz(rINST_FULL),%ecx  # ecx<- obj->clazz
6433    movl    $.LstrClassCastException,%eax
6434    movl    offClassObject_descriptor(%ecx),%ecx
6435    movl    %eax,OUT_ARG0(%esp)     # arg0<- message
6436    movl    %ecx,OUT_ARG1(%esp)     # arg1<- obj->clazz->descriptor
6437    SPILL(rPC)
6438    call    dvmThrowExceptionWithClassMessage
6439    UNSPILL(rPC)
6440    jmp     common_exceptionThrown
6441
6442    /*
6443     * Resolution required.  This is the least-likely path, and we're
6444     * going to have to recreate some data.
6445     *
6446     *  rINST_FULL holds object
6447     */
6448.LOP_CHECK_CAST_resolve:
6449    GET_GLUE(%ecx)
6450    EXPORT_PC()
6451    movzwl  2(rPC),%eax                # eax<- BBBB
6452    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6453    movl    %eax,OUT_ARG1(%esp)        # arg1<- BBBB
6454    movl    offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6455    movl    $0,OUT_ARG2(%esp)         # arg2<- false
6456    movl    %ecx,OUT_ARG0(%esp)        # arg0<- method->clazz
6457    SPILL(rPC)
6458    call    dvmResolveClass            # eax<- resolved ClassObject ptr
6459    UNSPILL(rPC)
6460    testl   %eax,%eax                  # got null?
6461    je      common_exceptionThrown     # yes, handle exception
6462    movl    offObject_clazz(rINST_FULL),%ecx  # ecx<- obj->clazz
6463    jmp     .LOP_CHECK_CAST_resolved       # pick up where we left off
6464
6465/* continuation for OP_INSTANCE_OF */
6466
6467    /*
6468     * Trivial test failed, need to perform full check.  This is common.
6469     *  eax holds obj->clazz
6470     *  ecx holds class resolved from BBBB
6471     *  rINST_HI has BA
6472     *  rPC already spilled
6473     */
6474.LOP_INSTANCE_OF_fullcheck:
6475    movl    %eax,OUT_ARG0(%esp)
6476    movl    %ecx,OUT_ARG1(%esp)
6477    call    dvmInstanceofNonTrivial     # eax<- boolean result
6478    # fall through to OP_INSTANCE_OF_store
6479
6480    /*
6481     * eax holds boolean result
6482     * rINST_HI holds BA
6483     */
6484.LOP_INSTANCE_OF_store:
6485    UNSPILL(rPC)
6486    movzbl  rINST_HI,%ecx               # ecx<- BA
6487    FETCH_INST_WORD(2)
6488    andb    $0xf,%cl                   # ecl<- A
6489    ADVANCE_PC(2)
6490    SET_VREG(%eax,%ecx)                 # vA<- eax
6491    GOTO_NEXT
6492
6493    /*
6494     * Trivial test succeeded, save and bail.
6495     *  r9 holds A
6496     */
6497.LOP_INSTANCE_OF_trivial:
6498    UNSPILL(rPC)
6499    movzbl  rINST_HI,%ecx               # ecx<- BA
6500    FETCH_INST_WORD(2)
6501    andb    $0xf,%cl                   # ecl<- A
6502    ADVANCE_PC(2)
6503    movl    $1,%eax
6504    SET_VREG(%eax,%ecx)                  # vA<- true
6505    GOTO_NEXT
6506
6507    /*
6508     * Resolution required.  This is the least-likely path.
6509     *
6510     *  rPC holds BBBB
6511     *  rINST_HI holds BA
6512     */
6513.LOP_INSTANCE_OF_resolve:
6514    movl    rPC,OUT_ARG1(%esp)          # arg1<- BBBB
6515    GET_GLUE(%ecx)
6516    UNSPILL(rPC)
6517    movl    offGlue_method(%ecx),%ecx
6518    movl    $1,OUT_ARG2(%esp)          # arg2<- true
6519    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6520    EXPORT_PC()
6521    movl    %ecx,OUT_ARG0(%esp)         # arg0<- method->clazz
6522    call    dvmResolveClass             # eax<- resolved ClassObject ptr
6523    UNSPILL(rPC)
6524    testl   %eax,%eax                   # success?
6525    je      common_exceptionThrown      # no, handle exception
6526/* Now, we need to sync up with fast path.  We need eax to
6527 * hold the obj->clazz, and ecx to hold the resolved class
6528 */
6529    movl    %eax,%ecx                   # ecx<- resolved class
6530    movzbl  rINST_HI,%eax               # eax<- BA
6531    sarl    $4,%eax                    # eax<- B
6532    GET_VREG(%eax,%eax)                 # eax<- vB (obj)
6533    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
6534    jmp     .LOP_INSTANCE_OF_resolved
6535
6536/* continuation for OP_NEW_INSTANCE */
6537
6538.LOP_NEW_INSTANCE_initialized:  # on entry, ecx<- class
6539    /* TODO: remove test for interface/abstract, now done in verifier */
6540    testl     $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6541    movl      $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6542    jne       .LOP_NEW_INSTANCE_abstract
6543.LOP_NEW_INSTANCE_finish: # ecx=class
6544    movl     %ecx,OUT_ARG0(%esp)
6545    call     dvmAllocObject             # eax<- new object
6546    UNSPILL(rPC)
6547    movl     rINST_FULL,%ecx
6548    FETCH_INST_WORD(2)
6549    testl    %eax,%eax                  # success?
6550    je       common_exceptionThrown     # no, bail out
6551    SET_VREG(%eax,%ecx)
6552    ADVANCE_PC(2)
6553    GOTO_NEXT
6554
6555    /*
6556     * Class initialization required.
6557     *
6558     *  ecx holds class object
6559     */
6560.LOP_NEW_INSTANCE_needinit:
6561    SPILL_TMP(%ecx)                     # save object
6562    movl    %ecx,OUT_ARG0(%esp)
6563    call    dvmInitClass                # initialize class
6564    UNSPILL_TMP(%ecx)                   # restore object
6565    testl   %eax,%eax                   # success?
6566    jne     .LOP_NEW_INSTANCE_initialized     # success, continue
6567    UNSPILL(rPC)                        # failed, restore PC
6568    jmp     common_exceptionThrown      # go deal with init exception
6569
6570    /*
6571     * Resolution required.  This is the least-likely path.
6572     *
6573     */
6574.LOP_NEW_INSTANCE_resolve:
6575    GET_GLUE(%ecx)
6576    movzwl  2(rPC),%eax
6577    movl    offGlue_method(%ecx),%ecx   # ecx<- glue->method
6578    movl    %eax,OUT_ARG1(%esp)
6579    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6580    movl    $0,OUT_ARG2(%esp)
6581    movl    %ecx,OUT_ARG0(%esp)
6582    call    dvmResolveClass             # call(clazz,off,flags)
6583    movl    %eax,%ecx                   # ecx<- resolved ClassObject ptr
6584    testl   %ecx,%ecx                   # success?
6585    jne     .LOP_NEW_INSTANCE_resolved        # good to go
6586    UNSPILL(rPC)
6587    jmp     common_exceptionThrown      # no, handle exception
6588
6589    /*
6590     * TODO: remove this
6591     * We can't instantiate an abstract class or interface, so throw an
6592     * InstantiationError with the class descriptor as the message.
6593     *
6594     *  ecx holds class object
6595     */
6596.LOP_NEW_INSTANCE_abstract:
6597    movl    offClassObject_descriptor(%ecx),%eax
6598    movl    $.LstrInstantiationError,OUT_ARG0(%esp)
6599    movl    %eax,OUT_ARG1(%esp)
6600    call    dvmThrowExceptionWithClassMessage
6601    UNSPILL(rPC)
6602    jmp     common_exceptionThrown
6603
6604/* continuation for OP_NEW_ARRAY */
6605
6606    /*
6607     * Resolve class.  (This is an uncommon case.)
6608     *  ecx holds class (null here)
6609     *  eax holds array length (vB)
6610     */
6611.LOP_NEW_ARRAY_resolve:
6612    GET_GLUE(%ecx)
6613    SPILL_TMP(%eax)                    # save array length
6614    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6615    movzwl  2(rPC),%eax                # eax<- CCCC
6616    movl    offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6617    movl    %eax,OUT_ARG1(%esp)
6618    movl    $0,OUT_ARG2(%esp)
6619    movl    %ecx,OUT_ARG0(%esp)
6620    SPILL(rPC)
6621    call    dvmResolveClass            # eax<- call(clazz,ref,flag)
6622    UNSPILL(rPC)
6623    movl    %eax,%ecx
6624    UNSPILL_TMP(%eax)
6625    testl   %ecx,%ecx                  # successful resolution?
6626    je      common_exceptionThrown     # no, bail.
6627# fall through to OP_NEW_ARRAY_finish
6628
6629    /*
6630     * Finish allocation
6631     *
6632     * ecx holds class
6633     * eax holds array length (vB)
6634     */
6635.LOP_NEW_ARRAY_finish:
6636    movl    %ecx,OUT_ARG0(%esp)
6637    movl    %eax,OUT_ARG1(%esp)
6638    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6639    SPILL(rPC)
6640    call    dvmAllocArrayByClass    # eax<- call(clazz,length,flags)
6641    UNSPILL(rPC)
6642    testl   %eax,%eax               # failed?
6643    je      common_exceptionThrown  # yup - go handle
6644    movl    rINST_FULL,%ecx
6645    FETCH_INST_WORD(2)
6646    SET_VREG(%eax,%ecx)
6647    ADVANCE_PC(2)
6648    GOTO_NEXT
6649
6650/* continuation for OP_FILLED_NEW_ARRAY */
6651
6652.LOP_FILLED_NEW_ARRAY_more:
6653    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6654    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6655    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6656    UNSPILL(rPC)
6657    testl   %eax,%eax                         # null?
6658    je      common_exceptionThrown            # yes, handle it
6659
6660       # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6661
6662    /*
6663     * On entry:
6664     *    eax holds array class [r0]
6665     *    rINST_FULL holds AA or BB [r10]
6666     *    ecx is scratch
6667     *    rPC is valid, but has been spilled
6668     */
6669.LOP_FILLED_NEW_ARRAY_continue:
6670    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6671    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6672    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6673    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6674    GET_GLUE(%eax)
6675    cmpb    $'I',%cl                             # supported?
6676    je      1f
6677    cmpb    $'L',%cl
6678    je      1f
6679    cmpb    $'[',%cl
6680    jne      .LOP_FILLED_NEW_ARRAY_notimpl                  # no, not handled yet
66811:
6682    movl    %ecx,offGlue_retval+4(%eax)           # save type
6683    .if      (!0)
6684    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
6685    sarl    $4,rINST_FULL
6686    .endif
6687    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
6688    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
6689    UNSPILL(rPC)
6690    GET_GLUE(%ecx)
6691    testl   %eax,%eax                             # alloc successful?
6692    je      common_exceptionThrown                # no, handle exception
6693    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6694    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6695    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6696
6697/* at this point:
6698 *     eax is pointer to tgt
6699 *     rINST_FULL is length
6700 *     ecx is FEDC or CCCC
6701 *     TMP_SPILL is BA
6702 *     rPC is valid, but spilled
6703 *  We now need to copy values from registers into the array
6704 */
6705
6706    .if 0
6707    # set up src pointer
6708    SPILL(rFP)     # esi
6709    SPILL(rIBASE)   # edi
6710    movl    %eax,%edi         # set up dst ptr
6711    leal    (rFP,%ecx,4),%esi # set up src ptr
6712    movl    rINST_FULL,%ecx   # load count register
6713    FETCH_INST_WORD(3)
6714    rep
6715    movsd
6716    GET_GLUE(%ecx)
6717    UNSPILL(rIBASE)
6718    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6719    UNSPILL(rFP)
6720    .else
6721    testl  rINST_FULL,rINST_FULL
6722    je     4f
6723    UNSPILL_TMP(rPC)
6724    andl   $0x0f,rPC            # rPC<- 0000000A
6725    sall   $16,rPC              # rPC<- 000A0000
6726    orl    %ecx,rPC              # rpc<- 000AFEDC
67273:
6728    movl   $0xf,%ecx
6729    andl   rPC,%ecx           # ecx<- next reg to load
6730    GET_VREG(%ecx,%ecx)
6731    shrl   $4,rPC
6732    leal   4(%eax),%eax
6733    movl   %ecx,-4(%eax)
6734    sub    $1,rINST_FULL
6735    jne    3b
67364:
6737    GET_GLUE(%ecx)
6738    UNSPILL(rPC)
6739    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6740    FETCH_INST_WORD(3)
6741    .endif
6742
6743    cmpb    $'I',%al                        # Int array?
6744    je      5f                               # skip card mark if so
6745    movl    offGlue_retval(%ecx),%eax        # eax<- object head
6746    movl    offGlue_cardTable(%ecx),%ecx     # card table base
6747    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
6748    movb    %cl,(%ecx,%eax)                  # mark card
67495:
6750    ADVANCE_PC(3)
6751    GOTO_NEXT
6752
6753
6754    /*
6755     * Throw an exception indicating that we have not implemented this
6756     * mode of filled-new-array.
6757     */
6758.LOP_FILLED_NEW_ARRAY_notimpl:
6759    movl    $.LstrInternalError,%eax
6760    movl    %eax,OUT_ARG0(%esp)
6761    movl    $.LstrFilledNewArrayNotImpl,%eax
6762    movl    %eax,OUT_ARG1(%esp)
6763    call    dvmThrowException
6764    UNSPILL(rPC)
6765    jmp     common_exceptionThrown
6766
6767/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6768
6769.LOP_FILLED_NEW_ARRAY_RANGE_more:
6770    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6771    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6772    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6773    UNSPILL(rPC)
6774    testl   %eax,%eax                         # null?
6775    je      common_exceptionThrown            # yes, handle it
6776
6777       # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6778
6779    /*
6780     * On entry:
6781     *    eax holds array class [r0]
6782     *    rINST_FULL holds AA or BB [r10]
6783     *    ecx is scratch
6784     *    rPC is valid, but has been spilled
6785     */
6786.LOP_FILLED_NEW_ARRAY_RANGE_continue:
6787    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6788    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6789    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6790    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6791    GET_GLUE(%eax)
6792    cmpb    $'I',%cl                             # supported?
6793    je      1f
6794    cmpb    $'L',%cl
6795    je      1f
6796    cmpb    $'[',%cl
6797    jne      .LOP_FILLED_NEW_ARRAY_RANGE_notimpl                  # no, not handled yet
67981:
6799    movl    %ecx,offGlue_retval+4(%eax)           # save type
6800    .if      (!1)
6801    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
6802    sarl    $4,rINST_FULL
6803    .endif
6804    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
6805    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
6806    UNSPILL(rPC)
6807    GET_GLUE(%ecx)
6808    testl   %eax,%eax                             # alloc successful?
6809    je      common_exceptionThrown                # no, handle exception
6810    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6811    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6812    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6813
6814/* at this point:
6815 *     eax is pointer to tgt
6816 *     rINST_FULL is length
6817 *     ecx is FEDC or CCCC
6818 *     TMP_SPILL is BA
6819 *     rPC is valid, but spilled
6820 *  We now need to copy values from registers into the array
6821 */
6822
6823    .if 1
6824    # set up src pointer
6825    SPILL(rFP)     # esi
6826    SPILL(rIBASE)   # edi
6827    movl    %eax,%edi         # set up dst ptr
6828    leal    (rFP,%ecx,4),%esi # set up src ptr
6829    movl    rINST_FULL,%ecx   # load count register
6830    FETCH_INST_WORD(3)
6831    rep
6832    movsd
6833    GET_GLUE(%ecx)
6834    UNSPILL(rIBASE)
6835    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6836    UNSPILL(rFP)
6837    .else
6838    testl  rINST_FULL,rINST_FULL
6839    je     4f
6840    UNSPILL_TMP(rPC)
6841    andl   $0x0f,rPC            # rPC<- 0000000A
6842    sall   $16,rPC              # rPC<- 000A0000
6843    orl    %ecx,rPC              # rpc<- 000AFEDC
68443:
6845    movl   $0xf,%ecx
6846    andl   rPC,%ecx           # ecx<- next reg to load
6847    GET_VREG(%ecx,%ecx)
6848    shrl   $4,rPC
6849    leal   4(%eax),%eax
6850    movl   %ecx,-4(%eax)
6851    sub    $1,rINST_FULL
6852    jne    3b
68534:
6854    GET_GLUE(%ecx)
6855    UNSPILL(rPC)
6856    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
6857    FETCH_INST_WORD(3)
6858    .endif
6859
6860    cmpb    $'I',%al                        # Int array?
6861    je      5f                               # skip card mark if so
6862    movl    offGlue_retval(%ecx),%eax        # eax<- object head
6863    movl    offGlue_cardTable(%ecx),%ecx     # card table base
6864    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
6865    movb    %cl,(%ecx,%eax)                  # mark card
68665:
6867    ADVANCE_PC(3)
6868    GOTO_NEXT
6869
6870
6871    /*
6872     * Throw an exception indicating that we have not implemented this
6873     * mode of filled-new-array.
6874     */
6875.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6876    movl    $.LstrInternalError,%eax
6877    movl    %eax,OUT_ARG0(%esp)
6878    movl    $.LstrFilledNewArrayNotImpl,%eax
6879    movl    %eax,OUT_ARG1(%esp)
6880    call    dvmThrowException
6881    UNSPILL(rPC)
6882    jmp     common_exceptionThrown
6883
6884/* continuation for OP_CMPL_FLOAT */
6885
6886.LOP_CMPL_FLOAT_isNaN:
6887    movl      $-1,%ecx
6888    jmp       .LOP_CMPL_FLOAT_finish
6889
6890/* continuation for OP_CMPG_FLOAT */
6891
6892.LOP_CMPG_FLOAT_isNaN:
6893    movl      $1,%ecx
6894    jmp       .LOP_CMPG_FLOAT_finish
6895
6896/* continuation for OP_CMPL_DOUBLE */
6897
6898.LOP_CMPL_DOUBLE_isNaN:
6899    movl      $-1,%ecx
6900    jmp       .LOP_CMPL_DOUBLE_finish
6901
6902/* continuation for OP_CMPG_DOUBLE */
6903
6904.LOP_CMPG_DOUBLE_isNaN:
6905    movl      $1,%ecx
6906    jmp       .LOP_CMPG_DOUBLE_finish
6907
6908/* continuation for OP_CMP_LONG */
6909
6910.LOP_CMP_LONG_bigger:
6911    UNSPILL(rPC)
6912    movl      $1,%ecx
6913    jmp       .LOP_CMP_LONG_finish
6914.LOP_CMP_LONG_smaller:
6915    UNSPILL(rPC)
6916    movl      $-1,%ecx
6917.LOP_CMP_LONG_finish:
6918    SET_VREG(%ecx,rINST_FULL)
6919    FETCH_INST_WORD(2)
6920    ADVANCE_PC(2)
6921    GOTO_NEXT
6922
6923/* continuation for OP_AGET_WIDE */
6924
6925.LOP_AGET_WIDE_finish:
6926    leal      offArrayObject_contents(%eax,%ecx,8),%eax
6927    movl      (%eax),%ecx
6928    movl      4(%eax),%eax
6929    SET_VREG_WORD(%ecx,rINST_FULL,0)
6930    SET_VREG_WORD(%eax,rINST_FULL,1)
6931    FETCH_INST_WORD(2)
6932    ADVANCE_PC(2)
6933    GOTO_NEXT
6934
6935/* continuation for OP_APUT_WIDE */
6936
6937.LOP_APUT_WIDE_finish:
6938    leal      offArrayObject_contents(%eax,%ecx,8),%eax
6939    GET_VREG_WORD(%ecx,rINST_FULL,0)
6940    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)
6941    movl      rINST_FULL,4(%eax)
6942    FETCH_INST_WORD(2)
6943    movl      %ecx,(%eax)
6944    ADVANCE_PC(2)
6945    GOTO_NEXT
6946
6947/* continuation for OP_APUT_OBJECT */
6948
6949    /* On entry:
6950     *   eax<- array object
6951     *   ecx<- index
6952     *   rINST_FULL<- vAA
6953     */
6954.LOP_APUT_OBJECT_continue:
6955    leal      offArrayObject_contents(%eax,%ecx,4),%ecx
6956    testl     rINST_FULL,rINST_FULL     # storing null reference?
6957    je        .LOP_APUT_OBJECT_skip_check
6958    SPILL(rPC)
6959    SPILL_TMP(%ecx)
6960    movl      offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
6961    movl      offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6962    movl      %eax,OUT_ARG1(%esp)
6963    movl      %ecx,OUT_ARG0(%esp)
6964    call      dvmCanPutArrayElement     # test object type vs. array type
6965    UNSPILL(rPC)
6966    UNSPILL_TMP(%ecx)
6967    testl     %eax,%eax
6968    GET_GLUE(%eax)
6969    je        common_errArrayStore
6970    movl      offGlue_cardTable(%eax),%eax   # get card table base
6971    movl      rINST_FULL,(%ecx)
6972    FETCH_INST_WORD(2)
6973    shrl      $GC_CARD_SHIFT,%ecx           # convert addr to card number
6974    movb      %al,(%eax,%ecx)                # mark card
6975    ADVANCE_PC(2)
6976    GOTO_NEXT
6977
6978.LOP_APUT_OBJECT_skip_check:
6979    movl      rINST_FULL,(%ecx)
6980    FETCH_INST_WORD(2)
6981    ADVANCE_PC(2)
6982    GOTO_NEXT
6983
6984/* continuation for OP_IGET */
6985
6986
6987.LOP_IGET_resolve:
6988    EXPORT_PC()
6989    SPILL(rPC)
6990    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6991    UNSPILL(rIBASE)
6992    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6993    SPILL_TMP(%ecx)                               # save object pointer across call
6994    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6995    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6996    UNSPILL_TMP(%ecx)
6997    UNSPILL(rPC)
6998    testl   %eax,%eax                             #  ... which returns InstrField ptr
6999    jne     .LOP_IGET_finish
7000    jmp     common_exceptionThrown
7001
7002.LOP_IGET_finish:
7003    /*
7004     * Currently:
7005     *   eax holds resolved field
7006     *   ecx holds object
7007     *   rIBASE is scratch, but needs to be unspilled
7008     *   rINST_FULL holds A
7009     */
7010    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7011    UNSPILL(rIBASE)
7012    testl   %ecx,%ecx                            # object null?
7013    je      common_errNullObject                 # object was null
7014    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7015    movl    rINST_FULL,%eax                      # eax<- A
7016    FETCH_INST_WORD(2)
7017    SET_VREG(%ecx,%eax)
7018    ADVANCE_PC(2)
7019    GOTO_NEXT
7020
7021/* continuation for OP_IGET_WIDE */
7022
7023
7024.LOP_IGET_WIDE_resolve:
7025    EXPORT_PC()
7026    SPILL(rPC)
7027    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7028    UNSPILL(rIBASE)
7029    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7030    SPILL_TMP(%ecx)                               # save object pointer across call
7031    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7032    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7033    UNSPILL_TMP(%ecx)
7034    UNSPILL(rPC)
7035    testl   %eax,%eax                             #  ... which returns InstrField ptr
7036    jne     .LOP_IGET_WIDE_finish
7037    jmp     common_exceptionThrown
7038
7039.LOP_IGET_WIDE_finish:
7040    /*
7041     * Currently:
7042     *   eax holds resolved field
7043     *   ecx holds object
7044     *   rIBASE is scratch, but needs to be unspilled
7045     *   rINST_FULL holds A
7046     */
7047    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7048    UNSPILL(rIBASE)
7049    testl   %ecx,%ecx                            # object null?
7050    je      common_errNullObject                 # object was null
7051    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
7052    movl    (%eax),%ecx                          # ecx<- lsw
7053    movl    4(%eax),%eax                         # eax<- msw
7054    SET_VREG_WORD(%ecx,rINST_FULL,0)
7055    SET_VREG_WORD(%eax,rINST_FULL,1)
7056    FETCH_INST_WORD(2)
7057    ADVANCE_PC(2)
7058    GOTO_NEXT
7059
7060/* continuation for OP_IGET_OBJECT */
7061
7062
7063.LOP_IGET_OBJECT_resolve:
7064    EXPORT_PC()
7065    SPILL(rPC)
7066    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7067    UNSPILL(rIBASE)
7068    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7069    SPILL_TMP(%ecx)                               # save object pointer across call
7070    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7071    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7072    UNSPILL_TMP(%ecx)
7073    UNSPILL(rPC)
7074    testl   %eax,%eax                             #  ... which returns InstrField ptr
7075    jne     .LOP_IGET_OBJECT_finish
7076    jmp     common_exceptionThrown
7077
7078.LOP_IGET_OBJECT_finish:
7079    /*
7080     * Currently:
7081     *   eax holds resolved field
7082     *   ecx holds object
7083     *   rIBASE is scratch, but needs to be unspilled
7084     *   rINST_FULL holds A
7085     */
7086    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7087    UNSPILL(rIBASE)
7088    testl   %ecx,%ecx                            # object null?
7089    je      common_errNullObject                 # object was null
7090    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7091    movl    rINST_FULL,%eax                      # eax<- A
7092    FETCH_INST_WORD(2)
7093    SET_VREG(%ecx,%eax)
7094    ADVANCE_PC(2)
7095    GOTO_NEXT
7096
7097/* continuation for OP_IGET_BOOLEAN */
7098
7099
7100.LOP_IGET_BOOLEAN_resolve:
7101    EXPORT_PC()
7102    SPILL(rPC)
7103    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7104    UNSPILL(rIBASE)
7105    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7106    SPILL_TMP(%ecx)                               # save object pointer across call
7107    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7108    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7109    UNSPILL_TMP(%ecx)
7110    UNSPILL(rPC)
7111    testl   %eax,%eax                             #  ... which returns InstrField ptr
7112    jne     .LOP_IGET_BOOLEAN_finish
7113    jmp     common_exceptionThrown
7114
7115.LOP_IGET_BOOLEAN_finish:
7116    /*
7117     * Currently:
7118     *   eax holds resolved field
7119     *   ecx holds object
7120     *   rIBASE is scratch, but needs to be unspilled
7121     *   rINST_FULL holds A
7122     */
7123    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7124    UNSPILL(rIBASE)
7125    testl   %ecx,%ecx                            # object null?
7126    je      common_errNullObject                 # object was null
7127    movzbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7128    movl    rINST_FULL,%eax                      # eax<- A
7129    FETCH_INST_WORD(2)
7130    SET_VREG(%ecx,%eax)
7131    ADVANCE_PC(2)
7132    GOTO_NEXT
7133
7134/* continuation for OP_IGET_BYTE */
7135
7136
7137.LOP_IGET_BYTE_resolve:
7138    EXPORT_PC()
7139    SPILL(rPC)
7140    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7141    UNSPILL(rIBASE)
7142    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7143    SPILL_TMP(%ecx)                               # save object pointer across call
7144    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7145    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7146    UNSPILL_TMP(%ecx)
7147    UNSPILL(rPC)
7148    testl   %eax,%eax                             #  ... which returns InstrField ptr
7149    jne     .LOP_IGET_BYTE_finish
7150    jmp     common_exceptionThrown
7151
7152.LOP_IGET_BYTE_finish:
7153    /*
7154     * Currently:
7155     *   eax holds resolved field
7156     *   ecx holds object
7157     *   rIBASE is scratch, but needs to be unspilled
7158     *   rINST_FULL holds A
7159     */
7160    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7161    UNSPILL(rIBASE)
7162    testl   %ecx,%ecx                            # object null?
7163    je      common_errNullObject                 # object was null
7164    movsbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7165    movl    rINST_FULL,%eax                      # eax<- A
7166    FETCH_INST_WORD(2)
7167    SET_VREG(%ecx,%eax)
7168    ADVANCE_PC(2)
7169    GOTO_NEXT
7170
7171/* continuation for OP_IGET_CHAR */
7172
7173
7174.LOP_IGET_CHAR_resolve:
7175    EXPORT_PC()
7176    SPILL(rPC)
7177    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7178    UNSPILL(rIBASE)
7179    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7180    SPILL_TMP(%ecx)                               # save object pointer across call
7181    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7182    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7183    UNSPILL_TMP(%ecx)
7184    UNSPILL(rPC)
7185    testl   %eax,%eax                             #  ... which returns InstrField ptr
7186    jne     .LOP_IGET_CHAR_finish
7187    jmp     common_exceptionThrown
7188
7189.LOP_IGET_CHAR_finish:
7190    /*
7191     * Currently:
7192     *   eax holds resolved field
7193     *   ecx holds object
7194     *   rIBASE is scratch, but needs to be unspilled
7195     *   rINST_FULL holds A
7196     */
7197    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7198    UNSPILL(rIBASE)
7199    testl   %ecx,%ecx                            # object null?
7200    je      common_errNullObject                 # object was null
7201    movzwl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7202    movl    rINST_FULL,%eax                      # eax<- A
7203    FETCH_INST_WORD(2)
7204    SET_VREG(%ecx,%eax)
7205    ADVANCE_PC(2)
7206    GOTO_NEXT
7207
7208/* continuation for OP_IGET_SHORT */
7209
7210
7211.LOP_IGET_SHORT_resolve:
7212    EXPORT_PC()
7213    SPILL(rPC)
7214    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7215    UNSPILL(rIBASE)
7216    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7217    SPILL_TMP(%ecx)                               # save object pointer across call
7218    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7219    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7220    UNSPILL_TMP(%ecx)
7221    UNSPILL(rPC)
7222    testl   %eax,%eax                             #  ... which returns InstrField ptr
7223    jne     .LOP_IGET_SHORT_finish
7224    jmp     common_exceptionThrown
7225
7226.LOP_IGET_SHORT_finish:
7227    /*
7228     * Currently:
7229     *   eax holds resolved field
7230     *   ecx holds object
7231     *   rIBASE is scratch, but needs to be unspilled
7232     *   rINST_FULL holds A
7233     */
7234    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7235    UNSPILL(rIBASE)
7236    testl   %ecx,%ecx                            # object null?
7237    je      common_errNullObject                 # object was null
7238    movswl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7239    movl    rINST_FULL,%eax                      # eax<- A
7240    FETCH_INST_WORD(2)
7241    SET_VREG(%ecx,%eax)
7242    ADVANCE_PC(2)
7243    GOTO_NEXT
7244
7245/* continuation for OP_IPUT */
7246
7247
7248.LOP_IPUT_resolve:
7249    EXPORT_PC()
7250    SPILL(rPC)
7251    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7252    UNSPILL(rIBASE)
7253    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7254    SPILL_TMP(%ecx)                               # save object pointer across call
7255    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7256    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7257    UNSPILL_TMP(%ecx)
7258    UNSPILL(rPC)
7259    testl   %eax,%eax                             #  ... which returns InstrField ptr
7260    jne     .LOP_IPUT_finish
7261    jmp     common_exceptionThrown
7262
7263.LOP_IPUT_finish:
7264    /*
7265     * Currently:
7266     *   eax holds resolved field
7267     *   ecx holds object
7268     *   rIBASE is scratch, but needs to be unspilled
7269     *   rINST_FULL holds A
7270     */
7271    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7272    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7273    UNSPILL(rIBASE)
7274    testl   %ecx,%ecx                            # object null?
7275    je      common_errNullObject                 # object was null
7276    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7277    FETCH_INST_WORD(2)
7278    ADVANCE_PC(2)
7279    GOTO_NEXT
7280
7281/* continuation for OP_IPUT_WIDE */
7282
7283
7284.LOP_IPUT_WIDE_resolve:
7285    EXPORT_PC()
7286    SPILL(rPC)
7287    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7288    UNSPILL(rIBASE)
7289    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7290    SPILL_TMP(%ecx)                               # save object pointer across call
7291    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7292    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7293    UNSPILL_TMP(%ecx)
7294    UNSPILL(rPC)
7295    testl   %eax,%eax                             #  ... which returns InstrField ptr
7296    jne     .LOP_IPUT_WIDE_finish
7297    jmp     common_exceptionThrown
7298
7299.LOP_IPUT_WIDE_finish:
7300    /*
7301     * Currently:
7302     *   eax holds resolved field
7303     *   ecx holds object
7304     *   rIBASE is scratch, but needs to be unspilled
7305     *   rINST_FULL holds A
7306     */
7307    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7308    UNSPILL(rIBASE)
7309    testl   %ecx,%ecx                            # object null?
7310    je      common_errNullObject                 # object was null
7311    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
7312    GET_VREG_WORD(%ecx,rINST_FULL,0)             # ecx<- lsw
7313    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)       # rINST_FULL<- msw
7314    movl    rINST_FULL,4(%eax)
7315    FETCH_INST_WORD(2)
7316    movl    %ecx,(%eax)
7317    ADVANCE_PC(2)
7318    GOTO_NEXT
7319
7320/* continuation for OP_IPUT_OBJECT */
7321
7322
7323.LOP_IPUT_OBJECT_resolve:
7324    EXPORT_PC()
7325    SPILL(rPC)
7326    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7327    UNSPILL(rIBASE)
7328    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7329    SPILL_TMP(%ecx)                               # save object pointer across call
7330    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7331    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7332    UNSPILL_TMP(%ecx)
7333    UNSPILL(rPC)
7334    testl   %eax,%eax                             #  ... which returns InstrField ptr
7335    jne     .LOP_IPUT_OBJECT_finish
7336    jmp     common_exceptionThrown
7337
7338.LOP_IPUT_OBJECT_finish:
7339    /*
7340     * Currently:
7341     *   eax holds resolved field
7342     *   ecx holds object
7343     *   rIBASE is scratch, but needs to be unspilled
7344     *   rINST_FULL holds A
7345     */
7346    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7347    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7348    UNSPILL(rIBASE)
7349    testl   %ecx,%ecx                            # object null?
7350    je      common_errNullObject                 # object was null
7351    movl    rINST_FULL,(%ecx,%eax)          # obj.field <- v[A](8/16/32 bits)
7352    GET_GLUE(%eax)
7353    testl   rINST_FULL,rINST_FULL                # stored a NULL?
7354    movl    offGlue_cardTable(%eax),%eax         # get card table base
7355    FETCH_INST_WORD(2)
7356    je      1f                                   # skip card mark if null store
7357    shrl    $GC_CARD_SHIFT,%ecx                 # object head to card number
7358    movb    %al,(%eax,%ecx)                      # mark card
73591:
7360    ADVANCE_PC(2)
7361    GOTO_NEXT
7362
7363/* continuation for OP_IPUT_BOOLEAN */
7364
7365
7366.LOP_IPUT_BOOLEAN_resolve:
7367    EXPORT_PC()
7368    SPILL(rPC)
7369    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7370    UNSPILL(rIBASE)
7371    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7372    SPILL_TMP(%ecx)                               # save object pointer across call
7373    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7374    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7375    UNSPILL_TMP(%ecx)
7376    UNSPILL(rPC)
7377    testl   %eax,%eax                             #  ... which returns InstrField ptr
7378    jne     .LOP_IPUT_BOOLEAN_finish
7379    jmp     common_exceptionThrown
7380
7381.LOP_IPUT_BOOLEAN_finish:
7382    /*
7383     * Currently:
7384     *   eax holds resolved field
7385     *   ecx holds object
7386     *   rIBASE is scratch, but needs to be unspilled
7387     *   rINST_FULL holds A
7388     */
7389    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7390    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7391    UNSPILL(rIBASE)
7392    testl   %ecx,%ecx                            # object null?
7393    je      common_errNullObject                 # object was null
7394    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7395    FETCH_INST_WORD(2)
7396    ADVANCE_PC(2)
7397    GOTO_NEXT
7398
7399/* continuation for OP_IPUT_BYTE */
7400
7401
7402.LOP_IPUT_BYTE_resolve:
7403    EXPORT_PC()
7404    SPILL(rPC)
7405    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7406    UNSPILL(rIBASE)
7407    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7408    SPILL_TMP(%ecx)                               # save object pointer across call
7409    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7410    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7411    UNSPILL_TMP(%ecx)
7412    UNSPILL(rPC)
7413    testl   %eax,%eax                             #  ... which returns InstrField ptr
7414    jne     .LOP_IPUT_BYTE_finish
7415    jmp     common_exceptionThrown
7416
7417.LOP_IPUT_BYTE_finish:
7418    /*
7419     * Currently:
7420     *   eax holds resolved field
7421     *   ecx holds object
7422     *   rIBASE is scratch, but needs to be unspilled
7423     *   rINST_FULL holds A
7424     */
7425    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7426    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7427    UNSPILL(rIBASE)
7428    testl   %ecx,%ecx                            # object null?
7429    je      common_errNullObject                 # object was null
7430    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7431    FETCH_INST_WORD(2)
7432    ADVANCE_PC(2)
7433    GOTO_NEXT
7434
7435/* continuation for OP_IPUT_CHAR */
7436
7437
7438.LOP_IPUT_CHAR_resolve:
7439    EXPORT_PC()
7440    SPILL(rPC)
7441    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7442    UNSPILL(rIBASE)
7443    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7444    SPILL_TMP(%ecx)                               # save object pointer across call
7445    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7446    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7447    UNSPILL_TMP(%ecx)
7448    UNSPILL(rPC)
7449    testl   %eax,%eax                             #  ... which returns InstrField ptr
7450    jne     .LOP_IPUT_CHAR_finish
7451    jmp     common_exceptionThrown
7452
7453.LOP_IPUT_CHAR_finish:
7454    /*
7455     * Currently:
7456     *   eax holds resolved field
7457     *   ecx holds object
7458     *   rIBASE is scratch, but needs to be unspilled
7459     *   rINST_FULL holds A
7460     */
7461    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7462    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7463    UNSPILL(rIBASE)
7464    testl   %ecx,%ecx                            # object null?
7465    je      common_errNullObject                 # object was null
7466    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7467    FETCH_INST_WORD(2)
7468    ADVANCE_PC(2)
7469    GOTO_NEXT
7470
7471/* continuation for OP_IPUT_SHORT */
7472
7473
7474.LOP_IPUT_SHORT_resolve:
7475    EXPORT_PC()
7476    SPILL(rPC)
7477    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7478    UNSPILL(rIBASE)
7479    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7480    SPILL_TMP(%ecx)                               # save object pointer across call
7481    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7482    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7483    UNSPILL_TMP(%ecx)
7484    UNSPILL(rPC)
7485    testl   %eax,%eax                             #  ... which returns InstrField ptr
7486    jne     .LOP_IPUT_SHORT_finish
7487    jmp     common_exceptionThrown
7488
7489.LOP_IPUT_SHORT_finish:
7490    /*
7491     * Currently:
7492     *   eax holds resolved field
7493     *   ecx holds object
7494     *   rIBASE is scratch, but needs to be unspilled
7495     *   rINST_FULL holds A
7496     */
7497    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7498    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7499    UNSPILL(rIBASE)
7500    testl   %ecx,%ecx                            # object null?
7501    je      common_errNullObject                 # object was null
7502    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7503    FETCH_INST_WORD(2)
7504    ADVANCE_PC(2)
7505    GOTO_NEXT
7506
7507/* continuation for OP_SGET */
7508
7509    /*
7510     * Go resolve the field
7511     */
7512.LOP_SGET_resolve:
7513    GET_GLUE(%ecx)
7514    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7515    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7516    EXPORT_PC()                                 # could throw, need to export
7517    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7518    SPILL(rPC)
7519    movl     %eax,OUT_ARG1(%esp)
7520    movl     %ecx,OUT_ARG0(%esp)
7521    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7522    UNSPILL(rPC)
7523    testl    %eax,%eax
7524    jne      .LOP_SGET_finish                 # success, continue
7525    jmp      common_exceptionThrown             # no, handle exception
7526
7527/* continuation for OP_SGET_WIDE */
7528
7529    /*
7530     * Go resolve the field
7531     */
7532.LOP_SGET_WIDE_resolve:
7533    GET_GLUE(%ecx)
7534    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7535    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7536    EXPORT_PC()                                 # could throw, need to export
7537    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7538    SPILL(rPC)
7539    movl     %eax,OUT_ARG1(%esp)
7540    movl     %ecx,OUT_ARG0(%esp)
7541    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7542    UNSPILL(rPC)
7543    testl    %eax,%eax
7544    jne      .LOP_SGET_WIDE_finish                 # success, continue
7545    jmp      common_exceptionThrown             # no, handle exception
7546
7547/* continuation for OP_SGET_OBJECT */
7548
7549    /*
7550     * Go resolve the field
7551     */
7552.LOP_SGET_OBJECT_resolve:
7553    GET_GLUE(%ecx)
7554    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7555    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7556    EXPORT_PC()                                 # could throw, need to export
7557    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7558    SPILL(rPC)
7559    movl     %eax,OUT_ARG1(%esp)
7560    movl     %ecx,OUT_ARG0(%esp)
7561    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7562    UNSPILL(rPC)
7563    testl    %eax,%eax
7564    jne      .LOP_SGET_OBJECT_finish                 # success, continue
7565    jmp      common_exceptionThrown             # no, handle exception
7566
7567/* continuation for OP_SGET_BOOLEAN */
7568
7569    /*
7570     * Go resolve the field
7571     */
7572.LOP_SGET_BOOLEAN_resolve:
7573    GET_GLUE(%ecx)
7574    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7575    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7576    EXPORT_PC()                                 # could throw, need to export
7577    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7578    SPILL(rPC)
7579    movl     %eax,OUT_ARG1(%esp)
7580    movl     %ecx,OUT_ARG0(%esp)
7581    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7582    UNSPILL(rPC)
7583    testl    %eax,%eax
7584    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
7585    jmp      common_exceptionThrown             # no, handle exception
7586
7587/* continuation for OP_SGET_BYTE */
7588
7589    /*
7590     * Go resolve the field
7591     */
7592.LOP_SGET_BYTE_resolve:
7593    GET_GLUE(%ecx)
7594    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7595    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7596    EXPORT_PC()                                 # could throw, need to export
7597    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7598    SPILL(rPC)
7599    movl     %eax,OUT_ARG1(%esp)
7600    movl     %ecx,OUT_ARG0(%esp)
7601    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7602    UNSPILL(rPC)
7603    testl    %eax,%eax
7604    jne      .LOP_SGET_BYTE_finish                 # success, continue
7605    jmp      common_exceptionThrown             # no, handle exception
7606
7607/* continuation for OP_SGET_CHAR */
7608
7609    /*
7610     * Go resolve the field
7611     */
7612.LOP_SGET_CHAR_resolve:
7613    GET_GLUE(%ecx)
7614    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7615    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7616    EXPORT_PC()                                 # could throw, need to export
7617    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7618    SPILL(rPC)
7619    movl     %eax,OUT_ARG1(%esp)
7620    movl     %ecx,OUT_ARG0(%esp)
7621    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7622    UNSPILL(rPC)
7623    testl    %eax,%eax
7624    jne      .LOP_SGET_CHAR_finish                 # success, continue
7625    jmp      common_exceptionThrown             # no, handle exception
7626
7627/* continuation for OP_SGET_SHORT */
7628
7629    /*
7630     * Go resolve the field
7631     */
7632.LOP_SGET_SHORT_resolve:
7633    GET_GLUE(%ecx)
7634    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7635    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7636    EXPORT_PC()                                 # could throw, need to export
7637    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7638    SPILL(rPC)
7639    movl     %eax,OUT_ARG1(%esp)
7640    movl     %ecx,OUT_ARG0(%esp)
7641    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7642    UNSPILL(rPC)
7643    testl    %eax,%eax
7644    jne      .LOP_SGET_SHORT_finish                 # success, continue
7645    jmp      common_exceptionThrown             # no, handle exception
7646
7647/* continuation for OP_SPUT */
7648
7649    /*
7650     * Go resolve the field
7651     */
7652.LOP_SPUT_resolve:
7653    GET_GLUE(%ecx)
7654    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7655    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7656    EXPORT_PC()                                 # could throw, need to export
7657    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7658    SPILL(rPC)
7659    movl     %eax,OUT_ARG1(%esp)
7660    movl     %ecx,OUT_ARG0(%esp)
7661    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7662    UNSPILL(rPC)
7663    testl    %eax,%eax
7664    jne      .LOP_SPUT_finish                 # success, continue
7665    jmp      common_exceptionThrown             # no, handle exception
7666
7667/* continuation for OP_SPUT_WIDE */
7668
7669    /*
7670     * Go resolve the field
7671     */
7672.LOP_SPUT_WIDE_resolve:
7673    GET_GLUE(%ecx)
7674    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7675    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7676    EXPORT_PC()                                 # could throw, need to export
7677    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7678    SPILL(rPC)
7679    movl     %eax,OUT_ARG1(%esp)
7680    movl     %ecx,OUT_ARG0(%esp)
7681    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7682    UNSPILL(rPC)
7683    testl    %eax,%eax
7684    jne      .LOP_SPUT_WIDE_finish                 # success, continue
7685    jmp      common_exceptionThrown             # no, handle exception
7686
7687/* continuation for OP_SPUT_OBJECT */
7688
7689
7690.LOP_SPUT_OBJECT_continue:
7691    movl      %ecx,offStaticField_value(%eax)
7692    testl     %ecx,%ecx
7693    GET_GLUE(%ecx)
7694    FETCH_INST_WORD(2)
7695    je        1f
7696    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
7697    shrl      $GC_CARD_SHIFT,%eax               # head to card number
7698    movb      %cl,(%ecx,%eax)                    # mark card
76991:
7700    ADVANCE_PC(2)
7701    GOTO_NEXT
7702
7703.LOP_SPUT_OBJECT_resolve:
7704    GET_GLUE(%ecx)
7705    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7706    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7707    EXPORT_PC()                                 # could throw, need to export
7708    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7709    SPILL(rPC)
7710    movl     %eax,OUT_ARG1(%esp)
7711    movl     %ecx,OUT_ARG0(%esp)
7712    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7713    UNSPILL(rPC)
7714    testl    %eax,%eax
7715    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
7716    jmp      common_exceptionThrown             # no, handle exception
7717
7718/* continuation for OP_SPUT_BOOLEAN */
7719
7720    /*
7721     * Go resolve the field
7722     */
7723.LOP_SPUT_BOOLEAN_resolve:
7724    GET_GLUE(%ecx)
7725    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7726    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7727    EXPORT_PC()                                 # could throw, need to export
7728    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7729    SPILL(rPC)
7730    movl     %eax,OUT_ARG1(%esp)
7731    movl     %ecx,OUT_ARG0(%esp)
7732    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7733    UNSPILL(rPC)
7734    testl    %eax,%eax
7735    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
7736    jmp      common_exceptionThrown             # no, handle exception
7737
7738/* continuation for OP_SPUT_BYTE */
7739
7740    /*
7741     * Go resolve the field
7742     */
7743.LOP_SPUT_BYTE_resolve:
7744    GET_GLUE(%ecx)
7745    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7746    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7747    EXPORT_PC()                                 # could throw, need to export
7748    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7749    SPILL(rPC)
7750    movl     %eax,OUT_ARG1(%esp)
7751    movl     %ecx,OUT_ARG0(%esp)
7752    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7753    UNSPILL(rPC)
7754    testl    %eax,%eax
7755    jne      .LOP_SPUT_BYTE_finish                 # success, continue
7756    jmp      common_exceptionThrown             # no, handle exception
7757
7758/* continuation for OP_SPUT_CHAR */
7759
7760    /*
7761     * Go resolve the field
7762     */
7763.LOP_SPUT_CHAR_resolve:
7764    GET_GLUE(%ecx)
7765    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7766    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7767    EXPORT_PC()                                 # could throw, need to export
7768    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7769    SPILL(rPC)
7770    movl     %eax,OUT_ARG1(%esp)
7771    movl     %ecx,OUT_ARG0(%esp)
7772    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7773    UNSPILL(rPC)
7774    testl    %eax,%eax
7775    jne      .LOP_SPUT_CHAR_finish                 # success, continue
7776    jmp      common_exceptionThrown             # no, handle exception
7777
7778/* continuation for OP_SPUT_SHORT */
7779
7780    /*
7781     * Go resolve the field
7782     */
7783.LOP_SPUT_SHORT_resolve:
7784    GET_GLUE(%ecx)
7785    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7786    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7787    EXPORT_PC()                                 # could throw, need to export
7788    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7789    SPILL(rPC)
7790    movl     %eax,OUT_ARG1(%esp)
7791    movl     %ecx,OUT_ARG0(%esp)
7792    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7793    UNSPILL(rPC)
7794    testl    %eax,%eax
7795    jne      .LOP_SPUT_SHORT_finish                 # success, continue
7796    jmp      common_exceptionThrown             # no, handle exception
7797
7798/* continuation for OP_INVOKE_VIRTUAL */
7799
7800
7801.LOP_INVOKE_VIRTUAL_more:
7802    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7803    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7804    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7805    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7806    UNSPILL(rPC)
7807    testl     %eax,%eax                   # got null?
7808    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
7809    jmp       common_exceptionThrown      # yes, handle exception
7810
7811    /* At this point:
7812     *   eax = resolved base method
7813     *   ecx = scratch
7814     */
7815.LOP_INVOKE_VIRTUAL_continue:
7816    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7817    .if       (!0)
7818    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7819    .endif
7820    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7821    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7822    testl     %ecx,%ecx                 # null this?
7823    je        common_errNullObject      # go if so
7824    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7825    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7826    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7827    jmp       common_invokeMethodNoRange
7828
7829/* continuation for OP_INVOKE_SUPER */
7830
7831    /*
7832     * At this point:
7833     *  ecx = resolved base method [r0]
7834     *  eax = method->clazz [r9]
7835     */
7836.LOP_INVOKE_SUPER_continue:
7837    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7838    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7839    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7840    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
7841    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7842    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7843    jmp     common_invokeMethodNoRange
7844
7845
7846    /* At this point:
7847     * ecx = null (needs to be resolved base method)
7848     * eax = method->clazz
7849    */
7850.LOP_INVOKE_SUPER_resolve:
7851    SPILL_TMP(%eax)                     # method->clazz
7852    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7853    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7854    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7855    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7856    SPILL(rPC)
7857    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7858    UNSPILL(rPC)
7859    testl   %eax,%eax                   # got null?
7860    movl    %eax,%ecx                   # ecx<- resolved base method
7861    UNSPILL_TMP(%eax)                   # restore method->clazz
7862    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
7863    jmp     common_exceptionThrown      # handle exception
7864
7865    /*
7866     * Throw a NoSuchMethodError with the method name as the message.
7867     *  ecx = resolved base method
7868     */
7869.LOP_INVOKE_SUPER_nsm:
7870    movl    offMethod_name(%ecx),%eax
7871    mov     %eax,OUT_ARG1(%esp)
7872    jmp     common_errNoSuchMethod
7873
7874/* continuation for OP_INVOKE_DIRECT */
7875
7876    /*
7877     * On entry:
7878     *   TMP_SPILL  <- "this" register
7879     * Things a bit ugly on this path, but it's the less
7880     * frequent one.  We'll have to do some reloading.
7881     */
7882.LOP_INVOKE_DIRECT_resolve:
7883     SPILL_TMP(%ecx)
7884     GET_GLUE(%ecx)
7885     UNSPILL(rPC)
7886     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7887     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7888     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7889     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7890     movl     %eax,OUT_ARG1(%esp)
7891     movl     %ecx,OUT_ARG0(%esp)
7892     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7893     UNSPILL_TMP(%ecx)
7894     testl    %eax,%eax
7895     jne      .LOP_INVOKE_DIRECT_finish
7896     UNSPILL(rPC)
7897     jmp      common_exceptionThrown
7898
7899/* continuation for OP_INVOKE_STATIC */
7900
7901.LOP_INVOKE_STATIC_continue:
7902    movl      $METHOD_STATIC,%eax
7903    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7904    SPILL(rPC)
7905    call      dvmResolveMethod          # call(clazz,ref,flags)
7906    UNSPILL(rPC)
7907    testl     %eax,%eax                 # got null?
7908    jne       common_invokeMethodNoRange
7909    jmp       common_exceptionThrown
7910
7911/* continuation for OP_INVOKE_INTERFACE */
7912
7913.LOP_INVOKE_INTERFACE_continue:
7914    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7915    UNSPILL(rPC)
7916    testl      %eax,%eax
7917    je         common_exceptionThrown
7918    jmp        common_invokeMethodNoRange
7919
7920/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7921
7922
7923.LOP_INVOKE_VIRTUAL_RANGE_more:
7924    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7925    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7926    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7927    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7928    UNSPILL(rPC)
7929    testl     %eax,%eax                   # got null?
7930    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
7931    jmp       common_exceptionThrown      # yes, handle exception
7932
7933    /* At this point:
7934     *   eax = resolved base method
7935     *   ecx = scratch
7936     */
7937.LOP_INVOKE_VIRTUAL_RANGE_continue:
7938    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7939    .if       (!1)
7940    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7941    .endif
7942    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7943    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7944    testl     %ecx,%ecx                 # null this?
7945    je        common_errNullObject      # go if so
7946    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7947    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7948    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7949    jmp       common_invokeMethodRange
7950
7951/* continuation for OP_INVOKE_SUPER_RANGE */
7952
7953    /*
7954     * At this point:
7955     *  ecx = resolved base method [r0]
7956     *  eax = method->clazz [r9]
7957     */
7958.LOP_INVOKE_SUPER_RANGE_continue:
7959    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7960    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7961    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7962    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
7963    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7964    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7965    jmp     common_invokeMethodRange
7966
7967
7968    /* At this point:
7969     * ecx = null (needs to be resolved base method)
7970     * eax = method->clazz
7971    */
7972.LOP_INVOKE_SUPER_RANGE_resolve:
7973    SPILL_TMP(%eax)                     # method->clazz
7974    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7975    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7976    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7977    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7978    SPILL(rPC)
7979    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7980    UNSPILL(rPC)
7981    testl   %eax,%eax                   # got null?
7982    movl    %eax,%ecx                   # ecx<- resolved base method
7983    UNSPILL_TMP(%eax)                   # restore method->clazz
7984    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
7985    jmp     common_exceptionThrown      # handle exception
7986
7987    /*
7988     * Throw a NoSuchMethodError with the method name as the message.
7989     *  ecx = resolved base method
7990     */
7991.LOP_INVOKE_SUPER_RANGE_nsm:
7992    movl    offMethod_name(%ecx),%eax
7993    mov     %eax,OUT_ARG1(%esp)
7994    jmp     common_errNoSuchMethod
7995
7996/* continuation for OP_INVOKE_DIRECT_RANGE */
7997
7998    /*
7999     * On entry:
8000     *   TMP_SPILL  <- "this" register
8001     * Things a bit ugly on this path, but it's the less
8002     * frequent one.  We'll have to do some reloading.
8003     */
8004.LOP_INVOKE_DIRECT_RANGE_resolve:
8005     SPILL_TMP(%ecx)
8006     GET_GLUE(%ecx)
8007     UNSPILL(rPC)
8008     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
8009     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
8010     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
8011     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
8012     movl     %eax,OUT_ARG1(%esp)
8013     movl     %ecx,OUT_ARG0(%esp)
8014     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
8015     UNSPILL_TMP(%ecx)
8016     testl    %eax,%eax
8017     jne      .LOP_INVOKE_DIRECT_RANGE_finish
8018     UNSPILL(rPC)
8019     jmp      common_exceptionThrown
8020
8021/* continuation for OP_INVOKE_STATIC_RANGE */
8022
8023.LOP_INVOKE_STATIC_RANGE_continue:
8024    movl      $METHOD_STATIC,%eax
8025    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
8026    SPILL(rPC)
8027    call      dvmResolveMethod          # call(clazz,ref,flags)
8028    UNSPILL(rPC)
8029    testl     %eax,%eax                 # got null?
8030    jne       common_invokeMethodRange
8031    jmp       common_exceptionThrown
8032
8033/* continuation for OP_INVOKE_INTERFACE_RANGE */
8034
8035.LOP_INVOKE_INTERFACE_RANGE_continue:
8036    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
8037    UNSPILL(rPC)
8038    testl      %eax,%eax
8039    je         common_exceptionThrown
8040    jmp        common_invokeMethodRange
8041
8042/* continuation for OP_FLOAT_TO_INT */
8043
8044
8045.LOP_FLOAT_TO_INT_continue:
8046    .if 0
8047    movl     $0x80000000,%eax
8048    xorl     4(rFP,%ecx,4),%eax
8049    orl      (rFP,%ecx,4),%eax
8050    .else
8051    cmpl     $0x80000000,(rFP,%ecx,4)
8052    .endif
8053    je       .LOP_FLOAT_TO_INT_special_case # fix up result
8054
8055.LOP_FLOAT_TO_INT_finish:
8056    ADVANCE_PC(1)
8057    GOTO_NEXT
8058
8059.LOP_FLOAT_TO_INT_special_case:
8060    fnstsw   %ax
8061    sahf
8062    jp       .LOP_FLOAT_TO_INT_isNaN
8063    adcl     $-1,(rFP,%ecx,4)
8064    .if 0
8065    adcl     $-1,4(rFP,%ecx,4)
8066    .endif
8067   jmp       .LOP_FLOAT_TO_INT_finish
8068.LOP_FLOAT_TO_INT_isNaN:
8069    movl      $0,(rFP,%ecx,4)
8070    .if 0
8071    movl      $0,4(rFP,%ecx,4)
8072    .endif
8073    jmp       .LOP_FLOAT_TO_INT_finish
8074
8075/* continuation for OP_FLOAT_TO_LONG */
8076
8077
8078.LOP_FLOAT_TO_LONG_continue:
8079    .if 1
8080    movl     $0x80000000,%eax
8081    xorl     4(rFP,%ecx,4),%eax
8082    orl      (rFP,%ecx,4),%eax
8083    .else
8084    cmpl     $0x80000000,(rFP,%ecx,4)
8085    .endif
8086    je       .LOP_FLOAT_TO_LONG_special_case # fix up result
8087
8088.LOP_FLOAT_TO_LONG_finish:
8089    ADVANCE_PC(1)
8090    GOTO_NEXT
8091
8092.LOP_FLOAT_TO_LONG_special_case:
8093    fnstsw   %ax
8094    sahf
8095    jp       .LOP_FLOAT_TO_LONG_isNaN
8096    adcl     $-1,(rFP,%ecx,4)
8097    .if 1
8098    adcl     $-1,4(rFP,%ecx,4)
8099    .endif
8100   jmp       .LOP_FLOAT_TO_LONG_finish
8101.LOP_FLOAT_TO_LONG_isNaN:
8102    movl      $0,(rFP,%ecx,4)
8103    .if 1
8104    movl      $0,4(rFP,%ecx,4)
8105    .endif
8106    jmp       .LOP_FLOAT_TO_LONG_finish
8107
8108/* continuation for OP_DOUBLE_TO_INT */
8109
8110
8111.LOP_DOUBLE_TO_INT_continue:
8112    .if 0
8113    movl     $0x80000000,%eax
8114    xorl     4(rFP,%ecx,4),%eax
8115    orl      (rFP,%ecx,4),%eax
8116    .else
8117    cmpl     $0x80000000,(rFP,%ecx,4)
8118    .endif
8119    je       .LOP_DOUBLE_TO_INT_special_case # fix up result
8120
8121.LOP_DOUBLE_TO_INT_finish:
8122    ADVANCE_PC(1)
8123    GOTO_NEXT
8124
8125.LOP_DOUBLE_TO_INT_special_case:
8126    fnstsw   %ax
8127    sahf
8128    jp       .LOP_DOUBLE_TO_INT_isNaN
8129    adcl     $-1,(rFP,%ecx,4)
8130    .if 0
8131    adcl     $-1,4(rFP,%ecx,4)
8132    .endif
8133   jmp       .LOP_DOUBLE_TO_INT_finish
8134.LOP_DOUBLE_TO_INT_isNaN:
8135    movl      $0,(rFP,%ecx,4)
8136    .if 0
8137    movl      $0,4(rFP,%ecx,4)
8138    .endif
8139    jmp       .LOP_DOUBLE_TO_INT_finish
8140
8141/* continuation for OP_DOUBLE_TO_LONG */
8142
8143
8144.LOP_DOUBLE_TO_LONG_continue:
8145    .if 1
8146    movl     $0x80000000,%eax
8147    xorl     4(rFP,%ecx,4),%eax
8148    orl      (rFP,%ecx,4),%eax
8149    .else
8150    cmpl     $0x80000000,(rFP,%ecx,4)
8151    .endif
8152    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result
8153
8154.LOP_DOUBLE_TO_LONG_finish:
8155    ADVANCE_PC(1)
8156    GOTO_NEXT
8157
8158.LOP_DOUBLE_TO_LONG_special_case:
8159    fnstsw   %ax
8160    sahf
8161    jp       .LOP_DOUBLE_TO_LONG_isNaN
8162    adcl     $-1,(rFP,%ecx,4)
8163    .if 1
8164    adcl     $-1,4(rFP,%ecx,4)
8165    .endif
8166   jmp       .LOP_DOUBLE_TO_LONG_finish
8167.LOP_DOUBLE_TO_LONG_isNaN:
8168    movl      $0,(rFP,%ecx,4)
8169    .if 1
8170    movl      $0,4(rFP,%ecx,4)
8171    .endif
8172    jmp       .LOP_DOUBLE_TO_LONG_finish
8173
8174/* continuation for OP_DIV_INT */
8175.LOP_DIV_INT_continue_div:
8176    cltd
8177    idivl   %ecx
8178.LOP_DIV_INT_finish_div:
8179    movzbl   rINST_HI,%ecx         # ecl<- AA
8180    SET_VREG(%eax,%ecx)
8181    UNSPILL(rPC)
8182    FETCH_INST_WORD(2)
8183    ADVANCE_PC(2)
8184    GOTO_NEXT
8185
8186/* continuation for OP_REM_INT */
8187.LOP_REM_INT_continue_div:
8188    cltd
8189    idivl   %ecx
8190.LOP_REM_INT_finish_div:
8191    movzbl   rINST_HI,%ecx         # ecl<- AA
8192    SET_VREG(%edx,%ecx)
8193    UNSPILL(rPC)
8194    FETCH_INST_WORD(2)
8195    ADVANCE_PC(2)
8196    GOTO_NEXT
8197
8198/* continuation for OP_MUL_LONG */
8199
8200.LOP_MUL_LONG_continue:
8201    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8202    movzbl    rINST_HI,%ecx       # ecx<- A
8203    movl      %edx,4(rFP,%ecx,4)  # v[B+1]<- %edx
8204    UNSPILL(rPC)                  # restore rPC/%edx
8205    FETCH_INST_WORD(2)
8206    UNSPILL(rIBASE)
8207    movl      %eax,(rFP,%ecx,4)   # v[B]<- %eax
8208    ADVANCE_PC(2)
8209    GOTO_NEXT
8210
8211/* continuation for OP_DIV_LONG */
8212
8213.LOP_DIV_LONG_continue:
8214    call     __divdi3
8215.LOP_DIV_LONG_finish:
8216    movzbl   rINST_HI,%ecx
8217    SET_VREG_WORD(rPC,%ecx,1)
8218    UNSPILL(rPC)
8219    SET_VREG_WORD(%eax,%ecx,0)
8220    FETCH_INST_WORD(2)
8221    ADVANCE_PC(2)
8222    GOTO_NEXT
8223
8224.LOP_DIV_LONG_check_zero:
8225    testl   rPC,rPC
8226    jne     .LOP_DIV_LONG_notSpecial
8227    UNSPILL(rPC)
8228    jmp     common_errDivideByZero
8229.LOP_DIV_LONG_check_neg1:
8230    testl   rPC,%eax
8231    jne     .LOP_DIV_LONG_notSpecial
8232    GET_VREG_WORD(rPC,%ecx,0)
8233    GET_VREG_WORD(%ecx,%ecx,1)
8234    testl    rPC,rPC
8235    jne      .LOP_DIV_LONG_notSpecial1
8236    cmpl     $0x80000000,%ecx
8237    jne      .LOP_DIV_LONG_notSpecial1
8238    /* minint / -1, return minint on div, 0 on rem */
8239    xorl     %eax,%eax
8240    movl     $0x80000000,%edx
8241    jmp      .LOP_DIV_LONG_finish
8242
8243/* continuation for OP_REM_LONG */
8244
8245.LOP_REM_LONG_continue:
8246    call     __moddi3
8247.LOP_REM_LONG_finish:
8248    movzbl   rINST_HI,%ecx
8249    SET_VREG_WORD(rPC,%ecx,1)
8250    UNSPILL(rPC)
8251    SET_VREG_WORD(%eax,%ecx,0)
8252    FETCH_INST_WORD(2)
8253    ADVANCE_PC(2)
8254    GOTO_NEXT
8255
8256.LOP_REM_LONG_check_zero:
8257    testl   rPC,rPC
8258    jne     .LOP_REM_LONG_notSpecial
8259    UNSPILL(rPC)
8260    jmp     common_errDivideByZero
8261.LOP_REM_LONG_check_neg1:
8262    testl   rPC,%eax
8263    jne     .LOP_REM_LONG_notSpecial
8264    GET_VREG_WORD(rPC,%ecx,0)
8265    GET_VREG_WORD(%ecx,%ecx,1)
8266    testl    rPC,rPC
8267    jne      .LOP_REM_LONG_notSpecial1
8268    cmpl     $0x80000000,%ecx
8269    jne      .LOP_REM_LONG_notSpecial1
8270    /* minint / -1, return minint on div, 0 on rem */
8271    xorl     %eax,%eax
8272    movl     $0,%edx
8273    jmp      .LOP_REM_LONG_finish
8274
8275/* continuation for OP_SHL_LONG */
8276
8277.LOP_SHL_LONG_finish:
8278    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- %eax
8279    ADVANCE_PC(2)
8280    GOTO_NEXT
8281
8282/* continuation for OP_SHR_LONG */
8283
8284
8285.LOP_SHR_LONG_finish:
8286    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- eax
8287    ADVANCE_PC(2)
8288    GOTO_NEXT
8289
8290/* continuation for OP_USHR_LONG */
8291
8292
8293.LOP_USHR_LONG_finish:
8294    SET_VREG_WORD(%eax,%ecx,0)        # v[BB+0]<- eax
8295    FETCH_INST_WORD(2)
8296    ADVANCE_PC(2)
8297    GOTO_NEXT
8298
8299/* continuation for OP_DIV_INT_2ADDR */
8300.LOP_DIV_INT_2ADDR_continue_div2addr:
8301    cltd
8302    idivl   %ecx
8303.LOP_DIV_INT_2ADDR_finish_div2addr:
8304    SET_VREG(%eax,rINST_FULL)
8305    UNSPILL(rPC)
8306    FETCH_INST_WORD(1)
8307    ADVANCE_PC(1)
8308    GOTO_NEXT
8309
8310/* continuation for OP_REM_INT_2ADDR */
8311.LOP_REM_INT_2ADDR_continue_div2addr:
8312    cltd
8313    idivl   %ecx
8314.LOP_REM_INT_2ADDR_finish_div2addr:
8315    SET_VREG(%edx,rINST_FULL)
8316    UNSPILL(rPC)
8317    FETCH_INST_WORD(1)
8318    ADVANCE_PC(1)
8319    GOTO_NEXT
8320
8321/* continuation for OP_MUL_LONG_2ADDR */
8322
8323.LOP_MUL_LONG_2ADDR_continue:
8324    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8325    movl      %edx,4(rIBASE)      # v[A+1]<- %edx
8326    UNSPILL(rPC)                  # restore rPC/%edx
8327    FETCH_INST_WORD(1)
8328    movl      %eax,(rIBASE)       # v[A]<- %eax
8329    UNSPILL(rFP)
8330    UNSPILL(rIBASE)
8331    ADVANCE_PC(1)
8332    GOTO_NEXT
8333
8334/* continuation for OP_DIV_LONG_2ADDR */
8335
8336.LOP_DIV_LONG_2ADDR_continue:
8337    movl     %eax,OUT_ARG3(%esp)
8338    movl     rPC,OUT_ARG0(%esp)
8339    movl     %ecx,OUT_ARG1(%esp)
8340    call     __divdi3
8341.LOP_DIV_LONG_2ADDR_finish:
8342    movl     rINST_FULL,%ecx
8343    SET_VREG_WORD(rPC,%ecx,1)
8344    UNSPILL(rPC)
8345    SET_VREG_WORD(%eax,%ecx,0)
8346    FETCH_INST_WORD(1)
8347    ADVANCE_PC(1)
8348    GOTO_NEXT
8349
8350.LOP_DIV_LONG_2ADDR_check_zero:
8351    testl   rPC,rPC
8352    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8353    UNSPILL(rPC)
8354    jmp     common_errDivideByZero
8355.LOP_DIV_LONG_2ADDR_check_neg1:
8356    testl   rPC,%eax
8357    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8358    GET_VREG_WORD(rPC,rINST_FULL,0)
8359    GET_VREG_WORD(%ecx,rINST_FULL,1)
8360    testl    rPC,rPC
8361    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8362    cmpl     $0x80000000,%ecx
8363    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8364    /* minint / -1, return minint on div, 0 on rem */
8365    xorl     %eax,%eax
8366    movl     $0x80000000,%edx
8367    jmp      .LOP_DIV_LONG_2ADDR_finish
8368
8369/* continuation for OP_REM_LONG_2ADDR */
8370
8371.LOP_REM_LONG_2ADDR_continue:
8372    movl     %eax,OUT_ARG3(%esp)
8373    movl     rPC,OUT_ARG0(%esp)
8374    movl     %ecx,OUT_ARG1(%esp)
8375    call     __moddi3
8376.LOP_REM_LONG_2ADDR_finish:
8377    movl     rINST_FULL,%ecx
8378    SET_VREG_WORD(rPC,%ecx,1)
8379    UNSPILL(rPC)
8380    SET_VREG_WORD(%eax,%ecx,0)
8381    FETCH_INST_WORD(1)
8382    ADVANCE_PC(1)
8383    GOTO_NEXT
8384
8385.LOP_REM_LONG_2ADDR_check_zero:
8386    testl   rPC,rPC
8387    jne     .LOP_REM_LONG_2ADDR_notSpecial
8388    UNSPILL(rPC)
8389    jmp     common_errDivideByZero
8390.LOP_REM_LONG_2ADDR_check_neg1:
8391    testl   rPC,%eax
8392    jne     .LOP_REM_LONG_2ADDR_notSpecial
8393    GET_VREG_WORD(rPC,rINST_FULL,0)
8394    GET_VREG_WORD(%ecx,rINST_FULL,1)
8395    testl    rPC,rPC
8396    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8397    cmpl     $0x80000000,%ecx
8398    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8399    /* minint / -1, return minint on div, 0 on rem */
8400    xorl     %eax,%eax
8401    movl     $0,%edx
8402    jmp      .LOP_REM_LONG_2ADDR_finish
8403
8404/* continuation for OP_SHL_LONG_2ADDR */
8405
8406
8407.LOP_SHL_LONG_2ADDR_finish:
8408    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8409    FETCH_INST_WORD(1)
8410    ADVANCE_PC(1)
8411    GOTO_NEXT
8412
8413/* continuation for OP_SHR_LONG_2ADDR */
8414
8415
8416.LOP_SHR_LONG_2ADDR_finish:
8417    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8418    FETCH_INST_WORD(1)
8419    ADVANCE_PC(1)
8420    GOTO_NEXT
8421
8422/* continuation for OP_USHR_LONG_2ADDR */
8423
8424
8425.LOP_USHR_LONG_2ADDR_finish:
8426    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[AA+0]<- eax
8427    FETCH_INST_WORD(1)
8428    ADVANCE_PC(1)
8429    GOTO_NEXT
8430
8431/* continuation for OP_DIV_INT_LIT16 */
8432.LOP_DIV_INT_LIT16_continue_div:
8433    cltd
8434    idivl   %ecx
8435.LOP_DIV_INT_LIT16_finish_div:
8436    SET_VREG(%eax,rINST_FULL)
8437    UNSPILL(rPC)
8438    FETCH_INST_WORD(2)
8439    ADVANCE_PC(2)
8440    GOTO_NEXT
8441
8442/* continuation for OP_REM_INT_LIT16 */
8443.LOP_REM_INT_LIT16_continue_div:
8444    cltd
8445    idivl   %ecx
8446.LOP_REM_INT_LIT16_finish_div:
8447    SET_VREG(%edx,rINST_FULL)
8448    UNSPILL(rPC)
8449    FETCH_INST_WORD(2)
8450    ADVANCE_PC(2)
8451    GOTO_NEXT
8452
8453/* continuation for OP_DIV_INT_LIT8 */
8454.LOP_DIV_INT_LIT8_continue_div:
8455    cltd
8456    idivl   %ecx
8457.LOP_DIV_INT_LIT8_finish_div:
8458    SET_VREG(%eax,rINST_FULL)
8459    UNSPILL(rPC)
8460    FETCH_INST_WORD(2)
8461    ADVANCE_PC(2)
8462    GOTO_NEXT
8463
8464/* continuation for OP_REM_INT_LIT8 */
8465.LOP_REM_INT_LIT8_continue_div:
8466    cltd
8467    idivl   %ecx
8468.LOP_REM_INT_LIT8_finish_div:
8469    SET_VREG(%edx,rINST_FULL)
8470    UNSPILL(rPC)
8471    FETCH_INST_WORD(2)
8472    ADVANCE_PC(2)
8473    GOTO_NEXT
8474
8475/* continuation for OP_IGET_VOLATILE */
8476
8477
8478.LOP_IGET_VOLATILE_resolve:
8479    EXPORT_PC()
8480    SPILL(rPC)
8481    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8482    UNSPILL(rIBASE)
8483    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8484    SPILL_TMP(%ecx)                               # save object pointer across call
8485    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8486    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8487    UNSPILL_TMP(%ecx)
8488    UNSPILL(rPC)
8489    testl   %eax,%eax                             #  ... which returns InstrField ptr
8490    jne     .LOP_IGET_VOLATILE_finish
8491    jmp     common_exceptionThrown
8492
8493.LOP_IGET_VOLATILE_finish:
8494    /*
8495     * Currently:
8496     *   eax holds resolved field
8497     *   ecx holds object
8498     *   rIBASE is scratch, but needs to be unspilled
8499     *   rINST_FULL holds A
8500     */
8501    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8502    UNSPILL(rIBASE)
8503    testl   %ecx,%ecx                            # object null?
8504    je      common_errNullObject                 # object was null
8505    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
8506    movl    rINST_FULL,%eax                      # eax<- A
8507    FETCH_INST_WORD(2)
8508    SET_VREG(%ecx,%eax)
8509    ADVANCE_PC(2)
8510    GOTO_NEXT
8511
8512/* continuation for OP_IPUT_VOLATILE */
8513
8514
8515.LOP_IPUT_VOLATILE_resolve:
8516    EXPORT_PC()
8517    SPILL(rPC)
8518    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8519    UNSPILL(rIBASE)
8520    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8521    SPILL_TMP(%ecx)                               # save object pointer across call
8522    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8523    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8524    UNSPILL_TMP(%ecx)
8525    UNSPILL(rPC)
8526    testl   %eax,%eax                             #  ... which returns InstrField ptr
8527    jne     .LOP_IPUT_VOLATILE_finish
8528    jmp     common_exceptionThrown
8529
8530.LOP_IPUT_VOLATILE_finish:
8531    /*
8532     * Currently:
8533     *   eax holds resolved field
8534     *   ecx holds object
8535     *   rIBASE is scratch, but needs to be unspilled
8536     *   rINST_FULL holds A
8537     */
8538    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
8539    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8540    UNSPILL(rIBASE)
8541    testl   %ecx,%ecx                            # object null?
8542    je      common_errNullObject                 # object was null
8543    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
8544    FETCH_INST_WORD(2)
8545    ADVANCE_PC(2)
8546    GOTO_NEXT
8547
8548/* continuation for OP_SGET_VOLATILE */
8549
8550    /*
8551     * Go resolve the field
8552     */
8553.LOP_SGET_VOLATILE_resolve:
8554    GET_GLUE(%ecx)
8555    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8556    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8557    EXPORT_PC()                                 # could throw, need to export
8558    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8559    SPILL(rPC)
8560    movl     %eax,OUT_ARG1(%esp)
8561    movl     %ecx,OUT_ARG0(%esp)
8562    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8563    UNSPILL(rPC)
8564    testl    %eax,%eax
8565    jne      .LOP_SGET_VOLATILE_finish                 # success, continue
8566    jmp      common_exceptionThrown             # no, handle exception
8567
8568/* continuation for OP_SPUT_VOLATILE */
8569
8570    /*
8571     * Go resolve the field
8572     */
8573.LOP_SPUT_VOLATILE_resolve:
8574    GET_GLUE(%ecx)
8575    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8576    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8577    EXPORT_PC()                                 # could throw, need to export
8578    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8579    SPILL(rPC)
8580    movl     %eax,OUT_ARG1(%esp)
8581    movl     %ecx,OUT_ARG0(%esp)
8582    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8583    UNSPILL(rPC)
8584    testl    %eax,%eax
8585    jne      .LOP_SPUT_VOLATILE_finish                 # success, continue
8586    jmp      common_exceptionThrown             # no, handle exception
8587
8588/* continuation for OP_IGET_OBJECT_VOLATILE */
8589
8590
8591.LOP_IGET_OBJECT_VOLATILE_resolve:
8592    EXPORT_PC()
8593    SPILL(rPC)
8594    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8595    UNSPILL(rIBASE)
8596    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8597    SPILL_TMP(%ecx)                               # save object pointer across call
8598    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8599    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8600    UNSPILL_TMP(%ecx)
8601    UNSPILL(rPC)
8602    testl   %eax,%eax                             #  ... which returns InstrField ptr
8603    jne     .LOP_IGET_OBJECT_VOLATILE_finish
8604    jmp     common_exceptionThrown
8605
8606.LOP_IGET_OBJECT_VOLATILE_finish:
8607    /*
8608     * Currently:
8609     *   eax holds resolved field
8610     *   ecx holds object
8611     *   rIBASE is scratch, but needs to be unspilled
8612     *   rINST_FULL holds A
8613     */
8614    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8615    UNSPILL(rIBASE)
8616    testl   %ecx,%ecx                            # object null?
8617    je      common_errNullObject                 # object was null
8618    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
8619    movl    rINST_FULL,%eax                      # eax<- A
8620    FETCH_INST_WORD(2)
8621    SET_VREG(%ecx,%eax)
8622    ADVANCE_PC(2)
8623    GOTO_NEXT
8624
8625/* continuation for OP_EXECUTE_INLINE */
8626
8627.LOP_EXECUTE_INLINE_continue:
8628    /*
8629     * Extract args, call function.
8630     *  ecx = #of args (0-4)
8631     *  eax = call index
8632     *  @esp = return addr
8633     *  esp is -4 from normal
8634     *
8635     *  Go ahead and load all 4 args, even if not used.
8636     */
8637    movzwl    4(rPC),rPC
8638
8639    movl      $0xf,%ecx
8640    andl      rPC,%ecx
8641    GET_VREG(%ecx,%ecx)
8642    sarl      $4,rPC
8643    movl      %ecx,4+OUT_ARG0(%esp)
8644
8645    movl      $0xf,%ecx
8646    andl      rPC,%ecx
8647    GET_VREG(%ecx,%ecx)
8648    sarl      $4,rPC
8649    movl      %ecx,4+OUT_ARG1(%esp)
8650
8651    movl      $0xf,%ecx
8652    andl      rPC,%ecx
8653    GET_VREG(%ecx,%ecx)
8654    sarl      $4,rPC
8655    movl      %ecx,4+OUT_ARG2(%esp)
8656
8657    movl      $0xf,%ecx
8658    andl      rPC,%ecx
8659    GET_VREG(%ecx,%ecx)
8660    sarl      $4,rPC
8661    movl      %ecx,4+OUT_ARG3(%esp)
8662
8663    sall      $4,%eax      # index *= sizeof(table entry)
8664    jmp       *gDvmInlineOpsTable(%eax)
8665    # will return to caller of .LOP_EXECUTE_INLINE_continue
8666
8667/* continuation for OP_IPUT_OBJECT_QUICK */
8668
8669.LOP_IPUT_OBJECT_QUICK_finish:
8670    testl     rINST_FULL,rINST_FULL         # did we store null?
8671    FETCH_INST_WORD(2)
8672    movl      offGlue_cardTable(%eax),%eax  # get card table base
8673    je        1f                            # skip card mark if null store
8674    shrl      $GC_CARD_SHIFT,%ecx          # object head to card number
8675    movb      %al,(%eax,%ecx)               # mark card
86761:
8677    ADVANCE_PC(2)
8678    GOTO_NEXT
8679
8680/* continuation for OP_IPUT_OBJECT_VOLATILE */
8681
8682
8683.LOP_IPUT_OBJECT_VOLATILE_resolve:
8684    EXPORT_PC()
8685    SPILL(rPC)
8686    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
8687    UNSPILL(rIBASE)
8688    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
8689    SPILL_TMP(%ecx)                               # save object pointer across call
8690    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
8691    call    dvmResolveInstField                   #  ... to dvmResolveInstField
8692    UNSPILL_TMP(%ecx)
8693    UNSPILL(rPC)
8694    testl   %eax,%eax                             #  ... which returns InstrField ptr
8695    jne     .LOP_IPUT_OBJECT_VOLATILE_finish
8696    jmp     common_exceptionThrown
8697
8698.LOP_IPUT_OBJECT_VOLATILE_finish:
8699    /*
8700     * Currently:
8701     *   eax holds resolved field
8702     *   ecx holds object
8703     *   rIBASE is scratch, but needs to be unspilled
8704     *   rINST_FULL holds A
8705     */
8706    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
8707    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
8708    UNSPILL(rIBASE)
8709    testl   %ecx,%ecx                            # object null?
8710    je      common_errNullObject                 # object was null
8711    movl    rINST_FULL,(%ecx,%eax)          # obj.field <- v[A](8/16/32 bits)
8712    GET_GLUE(%eax)
8713    testl   rINST_FULL,rINST_FULL                # stored a NULL?
8714    movl    offGlue_cardTable(%eax),%eax         # get card table base
8715    FETCH_INST_WORD(2)
8716    je      1f                                   # skip card mark if null store
8717    shrl    $GC_CARD_SHIFT,%ecx                 # object head to card number
8718    movb    %al,(%eax,%ecx)                      # mark card
87191:
8720    ADVANCE_PC(2)
8721    GOTO_NEXT
8722
8723/* continuation for OP_SGET_OBJECT_VOLATILE */
8724
8725    /*
8726     * Go resolve the field
8727     */
8728.LOP_SGET_OBJECT_VOLATILE_resolve:
8729    GET_GLUE(%ecx)
8730    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8731    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8732    EXPORT_PC()                                 # could throw, need to export
8733    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8734    SPILL(rPC)
8735    movl     %eax,OUT_ARG1(%esp)
8736    movl     %ecx,OUT_ARG0(%esp)
8737    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8738    UNSPILL(rPC)
8739    testl    %eax,%eax
8740    jne      .LOP_SGET_OBJECT_VOLATILE_finish                 # success, continue
8741    jmp      common_exceptionThrown             # no, handle exception
8742
8743/* continuation for OP_SPUT_OBJECT_VOLATILE */
8744
8745
8746.LOP_SPUT_OBJECT_VOLATILE_continue:
8747    movl      %ecx,offStaticField_value(%eax)
8748    testl     %ecx,%ecx
8749    GET_GLUE(%ecx)
8750    FETCH_INST_WORD(2)
8751    je        1f
8752    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
8753    shrl      $GC_CARD_SHIFT,%eax               # head to card number
8754    movb      %cl,(%ecx,%eax)                    # mark card
87551:
8756    ADVANCE_PC(2)
8757    GOTO_NEXT
8758
8759.LOP_SPUT_OBJECT_VOLATILE_resolve:
8760    GET_GLUE(%ecx)
8761    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
8762    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
8763    EXPORT_PC()                                 # could throw, need to export
8764    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
8765    SPILL(rPC)
8766    movl     %eax,OUT_ARG1(%esp)
8767    movl     %ecx,OUT_ARG0(%esp)
8768    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
8769    UNSPILL(rPC)
8770    testl    %eax,%eax
8771    jne      .LOP_SPUT_OBJECT_VOLATILE_finish                 # success, continue
8772    jmp      common_exceptionThrown             # no, handle exception
8773
8774    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8775    .global dvmAsmSisterEnd
8776dvmAsmSisterEnd:
8777
8778/* File: x86/entry.S */
8779/*
8780 * Copyright (C) 2008 The Android Open Source Project
8781 *
8782 * Licensed under the Apache License, Version 2.0 (the "License");
8783 * you may not use this file except in compliance with the License.
8784 * You may obtain a copy of the License at
8785 *
8786 *      http://www.apache.org/licenses/LICENSE-2.0
8787 *
8788 * Unless required by applicable law or agreed to in writing, software
8789 * distributed under the License is distributed on an "AS IS" BASIS,
8790 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8791 * See the License for the specific language governing permissions and
8792 * limitations under the License.
8793 */
8794
8795
8796    .text
8797    .global dvmMterpStdRun
8798    .type   dvmMterpStdRun, %function
8799/*
8800 * bool dvmMterpStdRun(MterpGlue* glue)
8801 *
8802 * Interpreter entry point.  Returns changeInterp.
8803 *
8804 */
8805dvmMterpStdRun:
8806    push    %ebp
8807    movl    %esp,%ebp
8808    push    %edi
8809    push    %esi
8810    push    %ebx
8811
8812/* at this point, stack is misaligned by 1 word
8813   We're allocating spill space for 6 words, plus
8814   outgoing argument (5 words) and local variables
8815   (4 words) - 15 words or 60 bytes total. See
8816   diagram in header.S
8817*/
8818    subl   $60,%esp
8819
8820/* Set up "named" registers */
8821    movl    IN_ARG0(%ebp),%ecx
8822    movl    %ecx,rGLUE_SPILL(%ebp)
8823    LOAD_PC_FROM_GLUE(%ecx)
8824    LOAD_FP_FROM_GLUE(%ecx)
8825    movl    $dvmAsmInstructionStart,rIBASE
8826
8827/* Remember %esp for future "longjmp" */
8828    movl    %esp,offGlue_bailPtr(%ecx)
8829
8830/* How to start? */
8831    movb    offGlue_entryPoint(%ecx),%al
8832
8833/* Normal start? */
8834    cmpb    $kInterpEntryInstr,%al
8835    jne     .Lnot_instr
8836
8837   /* Normal case: start executing the instruction at rPC */
8838    FETCH_INST()
8839    GOTO_NEXT
8840
8841.Lnot_instr:
8842    /* Reset to normal case */
8843    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8844    cmpb   $kInterpEntryReturn,%al
8845    je     common_returnFromMethod
8846    cmpb   $kInterpEntryThrow,%al
8847    je     common_exceptionThrown
8848    movzx  %al,%eax
8849    movl   %eax,OUT_ARG1(%esp)
8850    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
8851    call   printf
8852    call   dvmAbort
8853    /* Not reached */
8854
8855
8856    .global dvmMterpStdBail
8857    .type   dvmMterpStdBail, %function
8858/*
8859 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8860 *
8861 * Restore the stack pointer and PC from the save point established on entry.
8862 * This is essentially the same as a longjmp, but should be cheaper.  The
8863 * last instruction causes us to return to whoever called dvmMterpStdRun.
8864 *
8865 * We're not going to build a standard frame here, so the arg accesses will
8866 * look a little strange.
8867 *
8868 * On entry:
8869 *  esp+4 (arg0)  MterpGlue* glue
8870 *  esp+8 (arg1)  bool changeInterp
8871 */
8872dvmMterpStdBail:
8873    movl    4(%esp),%ecx                 # grab glue
8874    movl    8(%esp),%eax                 # changeInterp to return reg
8875    movl    offGlue_bailPtr(%ecx),%esp   # Stack back to normal
8876    addl    $60,%esp                    # Strip dvmMterpStdRun's frame
8877    pop     %ebx
8878    pop     %esi
8879    pop     %edi
8880    pop     %ebp
8881    ret                                  # return to dvmMterpStdRun's caller
8882
8883
8884/*
8885 * Strings
8886 */
8887    .section    .rodata
8888.LstrBadEntryPoint:
8889    .asciz  "Bad entry point %d\n"
8890
8891/* File: x86/footer.S */
8892/*
8893 * Copyright (C) 2008 The Android Open Source Project
8894 *
8895 * Licensed under the Apache License, Version 2.0 (the "License");
8896 * you may not use this file except in compliance with the License.
8897 * You may obtain a copy of the License at
8898 *
8899 *      http://www.apache.org/licenses/LICENSE-2.0
8900 *
8901 * Unless required by applicable law or agreed to in writing, software
8902 * distributed under the License is distributed on an "AS IS" BASIS,
8903 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8904 * See the License for the specific language governing permissions and
8905 * limitations under the License.
8906 */
8907/*
8908 * Common subroutines and data.
8909 */
8910
8911#if defined(WITH_JIT)
8912/*
8913 * Placeholder entries for x86 JIT
8914 */
8915    .global dvmJitToInterpPunt
8916dvmJitToInterpPunt:
8917    .global dvmJitToInterpSingleStep
8918dvmJitToInterpSingleStep:
8919    .global dvmJitToInterpNoChainNoProfile
8920dvmJitToInterpNoChainNoProfile:
8921    .global dvmJitToInterpTraceSelectNoChain
8922dvmJitToInterpTraceSelectNoChain:
8923    .global dvmJitToInterpTraceSelect
8924dvmJitToInterpTraceSelect:
8925    .global dvmJitToInterpBackwardBranch
8926dvmJitToInterpBackwardBranch:
8927    .global dvmJitToInterpNormal
8928dvmJitToInterpNormal:
8929    .global dvmJitToInterpNoChain
8930dvmJitToInterpNoChain:
8931    jmp  common_abort
8932#endif
8933
8934/*
8935 * Common code when a backwards branch is taken
8936 *
8937 * On entry:
8938 *   ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
8939 */
8940common_backwardBranch:
8941    GET_GLUE(%ecx)
8942    call   common_periodicChecks  # Note: expects rPC to be preserved
8943    ADVANCE_PC_INDEXED(rINST_FULL)
8944    FETCH_INST()
8945    GOTO_NEXT
8946
8947
8948
8949/*
8950 * Common code for method invocation with range.
8951 *
8952 * On entry:
8953 *   eax = Method* methodToCall
8954 *   rINST trashed, must reload
8955 */
8956
8957common_invokeMethodRange:
8958.LinvokeNewRange:
8959
8960   /*
8961    * prepare to copy args to "outs" area of current frame
8962    */
8963
8964    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
8965    movzwl      4(rPC), %ecx            # %ecx<- CCCC
8966    SPILL(rPC)
8967    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
8968    test        rINST_FULL, rINST_FULL
8969    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
8970    jz          .LinvokeArgsDone        # no args; jump to args done
8971
8972
8973   /*
8974    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
8975    * (very few methods have > 10 args; could unroll for common cases)
8976    */
8977
8978    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
8979    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
8980    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
8981    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
8982    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
89831:
8984    movl        (%ecx), %ebx            # %ebx<- vCCCC
8985    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
8986    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
8987    movl        %ebx, (%edx)            # *outs<- vCCCC
8988    lea         4(%edx), %edx           # outs++
8989    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
8990    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
8991    jmp         .LinvokeArgsDone        # continue
8992
8993   /*
8994    * %eax is "Method* methodToCall", the method we're trying to call
8995    * prepare to copy args to "outs" area of current frame
8996    */
8997
8998common_invokeMethodNoRange:
8999.LinvokeNewNoRange:
9000    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
9001    SPILL(rPC)
9002    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
9003    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
9004    je          .LinvokeArgsDone        # no args; jump to args done
9005    movzwl      4(rPC), %ecx            # %ecx<- GFED
9006    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
9007
9008   /*
9009    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
9010    */
9011
9012.LinvokeNonRange:
9013    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
9014    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
9015    jl          1f                      # handle 1 arg
9016    je          2f                      # handle 2 args
9017    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
9018    jl          3f                      # handle 3 args
9019    je          4f                      # handle 4 args
90205:
9021    andl        $15, rINST_FULL        # rINST<- A
9022    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9023    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
9024    movl        %ecx, (%edx)            # *outs<- vA
9025    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90264:
9027    shr         $12, %ecx              # %ecx<- G
9028    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9029    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
9030    movl        %ecx, (%edx)            # *outs<- vG
9031    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90323:
9033    and         $0x0f00, %ecx          # %ecx<- 0F00
9034    shr         $8, %ecx               # %ecx<- F
9035    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9036    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
9037    movl        %ecx, (%edx)            # *outs<- vF
9038    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90392:
9040    and         $0x00f0, %ecx          # %ecx<- 00E0
9041    shr         $4, %ecx               # %ecx<- E
9042    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
9043    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
9044    movl        %ecx, (%edx)            # *outs<- vE
9045    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
90461:
9047    and         $0x000f, %ecx          # %ecx<- 000D
9048    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
9049    movl        %ecx, -4(%edx)          # *--outs<- vD
90500:
9051
9052   /*
9053    * %eax is "Method* methodToCall", the method we're trying to call
9054    * find space for the new stack frame, check for overflow
9055    */
9056
9057.LinvokeArgsDone:
9058    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
9059    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
9060    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
9061    shl         $2, %edx               # %edx<- update offset
9062    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
9063    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
9064    GET_GLUE(%edx)                      # %edx<- pMterpGlue
9065    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
9066    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
9067    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
9068    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
9069    shl         $2, %ecx               # %ecx<- update offset for outsSize
9070    movl        %eax, %edx              # %edx<- newSaveArea
9071    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
9072    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
9073    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
9074    jl          .LstackOverflow         # handle frame overflow
9075
9076   /*
9077    * set up newSaveArea
9078    */
9079
9080#ifdef EASY_GDB
9081    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
9082    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
9083#endif
9084    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
9085    movl        rPC_SPILL(%ebp), %ecx
9086    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
9087    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
9088    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
9089    jne         .LinvokeNative          # handle native call
9090
9091   /*
9092    * Update "glue" values for the new method
9093    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
9094    */
9095
9096    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
9097    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
9098    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
9099    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
9100    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
9101    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
9102    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
9103    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
9104    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
9105    FETCH_INST()
9106    GOTO_NEXT                           # jump to methodToCall->insns
9107
9108   /*
9109    * Prep for the native call
9110    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
9111    */
9112
9113.LinvokeNative:
9114    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
9115    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9116    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
9117    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
9118    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
9119    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
9120    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
9121    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
9122    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
9123    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
9124    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
9125    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
9126    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
9127    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
9128    push        %edx                    # push parameter newFP
9129
9130    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
9131    lea         4(%esp), %esp
9132    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
9133    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
9134    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
9135    cmp         $0, offThread_exception(%eax) # check for exception
9136    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
9137    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
9138    UNSPILL(rPC)
9139    jne         common_exceptionThrown  # handle exception
9140    FETCH_INST_WORD(3)
9141    ADVANCE_PC(3)
9142    GOTO_NEXT                           # jump to next instruction
9143
9144.LstackOverflow:    # eax=methodToCall
9145    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
9146    GET_GLUE(%eax)                      # %eax<- pMterpGlue
9147    movl        offGlue_self(%eax), %eax # %eax<- glue->self
9148    movl        %eax, OUT_ARG0(%esp)    # push parameter self
9149    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
9150    UNSPILL(rPC)                        # return: void
9151    jmp         common_exceptionThrown  # handle exception
9152
9153
9154/*
9155 * Common invoke code (old-style).
9156 * TUNING:  Rewrite along lines of new armv5 code?
9157 *
9158 * On entry:
9159 *   eax = Method* methodToCall
9160 *   ecx = bool methodCallRange
9161 *   rINST trashed, must reload
9162 */
9163common_invokeOld:
9164    movl     %ecx,OUT_ARG1(%esp)     # arg1<- methodCallRange
9165    GET_GLUE(%ecx)
9166    movzwl  (rPC),rINST_FULL         # recover rINST
9167    movl     %eax,OUT_ARG2(%esp)     # arg2<- method
9168    movzwl   4(rPC),%eax             # eax<- GFED or CCCC
9169    SAVE_PC_TO_GLUE(%ecx)
9170    SAVE_FP_TO_GLUE(%ecx)
9171    movzbl   rINST_HI,rINST_FULL
9172    movl     rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
9173    movl     %ecx,OUT_ARG0(%esp)     # arg0<- GLUE
9174    movl     %eax,OUT_ARG4(%esp)     # arg4<- GFED/CCCC
9175    call     dvmMterp_invokeMethod
9176    jmp      common_resumeAfterGlueCall
9177
9178
9179/*
9180 * Do we need the thread to be suspended or have debugger/profiling activity?
9181 *
9182 * On entry:
9183 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
9184 *   ecx  -> GLUE pointer
9185 *   reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint
9186 *
9187 * Note: A call will normally kill %eax, rPC/%edx and %ecx.  To
9188 *       streamline the normal case, this routine will preserve rPC and
9189 *       %ecx in addition to the normal caller save regs.  The save/restore
9190 *       is a bit ugly, but will happen in the relatively uncommon path.
9191 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
9192 *       the suspendCount check so we can get both in 1 shot.
9193 */
9194common_periodicChecks:
9195    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
9196    cmpl    $0,(%eax)
9197    jne     1f
9198
91996:
9200    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
9201    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
9202    testl  %eax,%eax               # debugger enabled?
9203    je     2f
9204    movzbl (%eax),%eax             # get active count
92052:
9206    orl    (%ecx),%eax             # eax <- debuggerActive | activeProfilers
9207    GET_GLUE(%ecx)                 # restore rGLUE
9208    jne    3f                      # one or both active - switch interp
9209
92105:
9211    ret
9212
9213    /* Check for suspend */
92141:
9215    /*  At this point, the return pointer to the caller of
9216     *  common_periodicChecks is on the top of stack.  We need to preserve
9217     *  rPC(edx) and GLUE(ecx).  We'll spill rPC, and reload GLUE.
9218     *  The outgoing profile is:
9219     *      bool dvmCheckSuspendPending(Thread* self)
9220     *  Because we reached here via a call, go ahead and build a new frame.
9221     */
9222    EXPORT_PC()                         # need for precise GC
9223    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
9224    SPILL(rPC)                      # save edx
9225    push    %ebp
9226    movl    %esp,%ebp
9227    subl    $24,%esp
9228    movl    %eax,OUT_ARG0(%esp)
9229    call    dvmCheckSuspendPending
9230    addl    $24,%esp
9231    pop     %ebp
9232    UNSPILL(rPC)
9233    GET_GLUE(%ecx)
9234
9235    /*
9236     * Need to check to see if debugger or profiler flags got set
9237     * while we were suspended.
9238     */
9239    jmp    6b
9240
9241    /* Switch interpreters */
9242    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
9243     * "complete" the interpretation of backwards branches.  In effect, we
9244     * are completing the interpretation of the branch instruction here,
9245     * and the new interpreter will resume interpretation at the branch
9246     * target. However, a switch request recognized during the handling
9247     * of a return from method instruction results in an immediate abort,
9248     * and the new interpreter will resume by re-interpreting the return
9249     * instruction.
9250     */
92513:
9252    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
9253    GET_GLUE(%ecx)                 # bail expect GLUE already loaded
9254    movl    $1,rINST_FULL         # set changeInterp to true
9255    jmp     common_gotoBail
9256
9257
9258/*
9259 * Common code for handling a return instruction
9260 */
9261common_returnFromMethod:
9262    GET_GLUE(%ecx)
9263    /* Set entry mode in case we bail */
9264    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
9265    xorl    rINST_FULL,rINST_FULL   # zero offset in case we switch interps
9266    call    common_periodicChecks   # Note: expects %ecx to be preserved
9267
9268    SAVEAREA_FROM_FP(%eax,rFP)                    # eax<- saveArea (old)
9269    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
9270    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
9271    cmpl    $0,rINST_FULL                        # break?
9272    je      common_gotoBail    # break frame, bail out completely
9273
9274    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
9275    movl    offGlue_self(%ecx),%eax               # eax<- self
9276    movl    rINST_FULL,offGlue_method(%ecx)  # glue->method = newSave->meethod
9277    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
9278    movl    offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
9279    FETCH_INST_WORD(3)
9280    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
9281    ADVANCE_PC(3)
9282    movl    %eax,offGlue_methodClassDex(%ecx)
9283    /* not bailing - restore entry mode to default */
9284    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
9285    GOTO_NEXT
9286
9287/*
9288 * Prepare to strip the current frame and "longjump" back to caller of
9289 * dvmMterpStdRun.
9290 *
9291 * on entry:
9292 *    rINST_FULL holds changeInterp
9293 *    ecx holds glue pointer
9294 *
9295 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
9296 */
9297common_gotoBail:
9298    SAVE_PC_TO_GLUE(%ecx)                # export state to glue
9299    SAVE_FP_TO_GLUE(%ecx)
9300    movl   %ecx,OUT_ARG0(%esp)           # glue in arg0
9301    movl   rINST_FULL,OUT_ARG1(%esp)     # changeInterp in arg1
9302    call    dvmMterpStdBail              # bail out....
9303
9304
9305/*
9306 * After returning from a "glued" function, pull out the updated values
9307 * and start executing at the next instruction.
9308 */
9309 common_resumeAfterGlueCall:
9310     GET_GLUE(%ecx)
9311     LOAD_PC_FROM_GLUE(%ecx)
9312     LOAD_FP_FROM_GLUE(%ecx)
9313     FETCH_INST()
9314     GOTO_NEXT
9315
9316/*
9317 * Integer divide or mod by zero
9318 */
9319common_errDivideByZero:
9320    EXPORT_PC()
9321    movl    $.LstrArithmeticException,%eax
9322    movl    %eax,OUT_ARG0(%esp)
9323    movl    $.LstrDivideByZero,%eax
9324    movl    %eax,OUT_ARG1(%esp)
9325    SPILL(rPC)
9326    call    dvmThrowException
9327    UNSPILL(rPC)
9328    jmp     common_exceptionThrown
9329
9330/*
9331 * Attempt to allocate an array with a negative size.
9332 */
9333common_errNegativeArraySize:
9334    EXPORT_PC()
9335    movl    $.LstrNegativeArraySizeException,%eax
9336    movl    %eax,OUT_ARG0(%esp)
9337    xorl    %eax,%eax
9338    movl    %eax,OUT_ARG1(%esp)
9339    SPILL(rPC)
9340    call    dvmThrowException
9341    UNSPILL(rPC)
9342    jmp     common_exceptionThrown
9343
9344/*
9345 * Attempt to allocate an array with a negative size.
9346 */
9347common_errNoSuchMethod:
9348
9349    EXPORT_PC()
9350    movl    $.LstrNoSuchMethodError,%eax
9351    movl    %eax,OUT_ARG0(%esp)
9352    xorl    %eax,%eax
9353    movl    %eax,OUT_ARG1(%esp)
9354    SPILL(rPC)
9355    call    dvmThrowException
9356    UNSPILL(rPC)
9357    jmp     common_exceptionThrown
9358
9359/*
9360 * Hit a null object when we weren't expecting one.  Export the PC, throw a
9361 * NullPointerException and goto the exception processing code.
9362 */
9363common_errNullObject:
9364    EXPORT_PC()
9365    movl    $.LstrNullPointerException,%eax
9366    movl    %eax,OUT_ARG0(%esp)
9367    xorl    %eax,%eax
9368    movl    %eax,OUT_ARG1(%esp)
9369    SPILL(rPC)
9370    call    dvmThrowException
9371    UNSPILL(rPC)
9372    jmp     common_exceptionThrown
9373
9374/*
9375 * Array index exceeds max.
9376 */
9377common_errArrayIndex:
9378    EXPORT_PC()
9379    movl    $.LstrArrayIndexException,%eax
9380    movl    %eax,OUT_ARG0(%esp)
9381    xorl    %eax,%eax
9382    movl    %eax,OUT_ARG1(%esp)
9383    SPILL(rPC)
9384    call    dvmThrowException
9385    UNSPILL(rPC)
9386    jmp     common_exceptionThrown
9387/*
9388 * Invalid array value.
9389 */
9390common_errArrayStore:
9391    EXPORT_PC()
9392    movl    $.LstrArrayStoreException,%eax
9393    movl    %eax,OUT_ARG0(%esp)
9394    xorl    %eax,%eax
9395    movl    %eax,OUT_ARG1(%esp)
9396    SPILL(rPC)
9397    call    dvmThrowException
9398    UNSPILL(rPC)
9399    jmp     common_exceptionThrown
9400
9401/*
9402 * Somebody has thrown an exception.  Handle it.
9403 *
9404 * If the exception processing code returns to us (instead of falling
9405 * out of the interpreter), continue with whatever the next instruction
9406 * now happens to be.
9407 *
9408 * This does not return.
9409 */
9410common_exceptionThrown:
9411    GET_GLUE(%ecx)
9412    SAVE_PC_TO_GLUE(%ecx)
9413    SAVE_FP_TO_GLUE(%ecx)
9414    movl    %ecx,OUT_ARG0(%esp)
9415    call    dvmMterp_exceptionThrown
9416    jmp     common_resumeAfterGlueCall
9417
9418common_abort:
9419    movl    $0xdeadf00d,%eax
9420    call     *%eax
9421
9422
9423/*
9424 * Strings
9425 */
9426
9427    .section     .rodata
9428.LstrNullPointerException:
9429    .asciz    "Ljava/lang/NullPointerException;"
9430.LstrArithmeticException:
9431    .asciz  "Ljava/lang/ArithmeticException;"
9432.LstrDivideByZero:
9433    .asciz  "divide by zero"
9434.LstrArrayIndexException:
9435    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9436.LstrArrayStoreException:
9437    .asciz  "Ljava/lang/ArrayStoreException;"
9438.LstrNegativeArraySizeException:
9439    .asciz  "Ljava/lang/NegativeArraySizeException;"
9440.LstrInstantiationError:
9441    .asciz  "Ljava/lang/InstantiationError;"
9442.LstrClassCastException:
9443    .asciz  "Ljava/lang/ClassCastException;"
9444.LstrNoSuchMethodError:
9445    .asciz  "Ljava/lang/NoSuchMethodError;"
9446.LstrInternalError:
9447    .asciz  "Ljava/lang/InternalError;"
9448.LstrFilledNewArrayNotImpl:
9449    .asciz  "filled-new-array only implemented for 'int'"
9450
9451