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