InterpAsm-x86.S revision c35a2ef53d0cccd6f924eeba36633220ec67c32e
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/* File: x86/OP_IPUT.S */
2225
2226    /*
2227     * General 32-bit instance field put.
2228     *
2229     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2230     */
2231    /* op vA, vB, field@CCCC */
2232    GET_GLUE(%ecx)
2233    SPILL(rIBASE)                                 # need another reg
2234    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
2235    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
2236    movzbl  rINST_HI,%ecx                         # ecx<- BA
2237    sarl    $4,%ecx                              # ecx<- B
2238    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
2239    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
2240    andb    $0xf,rINST_LO                        # rINST_FULL<- A
2241    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
2242    movl    (%eax,rIBASE,4),%eax                  # resolved entry
2243    testl   %eax,%eax                             # is resolved entry null?
2244    jne     .LOP_IPUT_OBJECT_finish                    # no, already resolved
2245    movl    rIBASE,OUT_ARG1(%esp)
2246    GET_GLUE(rIBASE)
2247    jmp     .LOP_IPUT_OBJECT_resolve
2248
2249
2250/* ------------------------------ */
2251    .balign 64
2252.L_OP_IPUT_BOOLEAN: /* 0x5c */
2253/* File: x86/OP_IPUT_BOOLEAN.S */
2254/* File: x86/OP_IPUT.S */
2255
2256    /*
2257     * General 32-bit instance field put.
2258     *
2259     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2260     */
2261    /* op vA, vB, field@CCCC */
2262    GET_GLUE(%ecx)
2263    SPILL(rIBASE)                                 # need another reg
2264    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
2265    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
2266    movzbl  rINST_HI,%ecx                         # ecx<- BA
2267    sarl    $4,%ecx                              # ecx<- B
2268    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
2269    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
2270    andb    $0xf,rINST_LO                        # rINST_FULL<- A
2271    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
2272    movl    (%eax,rIBASE,4),%eax                  # resolved entry
2273    testl   %eax,%eax                             # is resolved entry null?
2274    jne     .LOP_IPUT_BOOLEAN_finish                    # no, already resolved
2275    movl    rIBASE,OUT_ARG1(%esp)
2276    GET_GLUE(rIBASE)
2277    jmp     .LOP_IPUT_BOOLEAN_resolve
2278
2279
2280/* ------------------------------ */
2281    .balign 64
2282.L_OP_IPUT_BYTE: /* 0x5d */
2283/* File: x86/OP_IPUT_BYTE.S */
2284/* File: x86/OP_IPUT.S */
2285
2286    /*
2287     * General 32-bit instance field put.
2288     *
2289     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2290     */
2291    /* op vA, vB, field@CCCC */
2292    GET_GLUE(%ecx)
2293    SPILL(rIBASE)                                 # need another reg
2294    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
2295    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
2296    movzbl  rINST_HI,%ecx                         # ecx<- BA
2297    sarl    $4,%ecx                              # ecx<- B
2298    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
2299    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
2300    andb    $0xf,rINST_LO                        # rINST_FULL<- A
2301    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
2302    movl    (%eax,rIBASE,4),%eax                  # resolved entry
2303    testl   %eax,%eax                             # is resolved entry null?
2304    jne     .LOP_IPUT_BYTE_finish                    # no, already resolved
2305    movl    rIBASE,OUT_ARG1(%esp)
2306    GET_GLUE(rIBASE)
2307    jmp     .LOP_IPUT_BYTE_resolve
2308
2309
2310/* ------------------------------ */
2311    .balign 64
2312.L_OP_IPUT_CHAR: /* 0x5e */
2313/* File: x86/OP_IPUT_CHAR.S */
2314/* File: x86/OP_IPUT.S */
2315
2316    /*
2317     * General 32-bit instance field put.
2318     *
2319     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2320     */
2321    /* op vA, vB, field@CCCC */
2322    GET_GLUE(%ecx)
2323    SPILL(rIBASE)                                 # need another reg
2324    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
2325    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
2326    movzbl  rINST_HI,%ecx                         # ecx<- BA
2327    sarl    $4,%ecx                              # ecx<- B
2328    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
2329    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
2330    andb    $0xf,rINST_LO                        # rINST_FULL<- A
2331    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
2332    movl    (%eax,rIBASE,4),%eax                  # resolved entry
2333    testl   %eax,%eax                             # is resolved entry null?
2334    jne     .LOP_IPUT_CHAR_finish                    # no, already resolved
2335    movl    rIBASE,OUT_ARG1(%esp)
2336    GET_GLUE(rIBASE)
2337    jmp     .LOP_IPUT_CHAR_resolve
2338
2339
2340/* ------------------------------ */
2341    .balign 64
2342.L_OP_IPUT_SHORT: /* 0x5f */
2343/* File: x86/OP_IPUT_SHORT.S */
2344/* File: x86/OP_IPUT.S */
2345
2346    /*
2347     * General 32-bit instance field put.
2348     *
2349     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2350     */
2351    /* op vA, vB, field@CCCC */
2352    GET_GLUE(%ecx)
2353    SPILL(rIBASE)                                 # need another reg
2354    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
2355    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
2356    movzbl  rINST_HI,%ecx                         # ecx<- BA
2357    sarl    $4,%ecx                              # ecx<- B
2358    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
2359    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
2360    andb    $0xf,rINST_LO                        # rINST_FULL<- A
2361    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
2362    movl    (%eax,rIBASE,4),%eax                  # resolved entry
2363    testl   %eax,%eax                             # is resolved entry null?
2364    jne     .LOP_IPUT_SHORT_finish                    # no, already resolved
2365    movl    rIBASE,OUT_ARG1(%esp)
2366    GET_GLUE(rIBASE)
2367    jmp     .LOP_IPUT_SHORT_resolve
2368
2369
2370/* ------------------------------ */
2371    .balign 64
2372.L_OP_SGET: /* 0x60 */
2373/* File: x86/OP_SGET.S */
2374    /*
2375     * General 32-bit SGET handler.
2376     *
2377     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2378     */
2379    /* op vAA, field@BBBB */
2380    GET_GLUE(%ecx)
2381    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2382    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2383    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2384    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2385    testl     %eax,%eax                          # resolved entry null?
2386    je        .LOP_SGET_resolve                # if not, make it so
2387.LOP_SGET_finish:     # field ptr in eax
2388    movl      offStaticField_value(%eax),%eax
2389    movzbl    rINST_HI,%ecx                      # ecx<- AA
2390    FETCH_INST_WORD(2)
2391    ADVANCE_PC(2)
2392    SET_VREG(%eax,%ecx)
2393    GOTO_NEXT
2394
2395/* ------------------------------ */
2396    .balign 64
2397.L_OP_SGET_WIDE: /* 0x61 */
2398/* File: x86/OP_SGET_WIDE.S */
2399    /*
2400     * 64-bit SGET handler.
2401     *
2402     */
2403    /* sget-wide vAA, field@BBBB */
2404    GET_GLUE(%ecx)
2405    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2406    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2407    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2408    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2409    testl     %eax,%eax                          # resolved entry null?
2410    je        .LOP_SGET_WIDE_resolve                # if not, make it so
2411.LOP_SGET_WIDE_finish:     # field ptr in eax
2412    movl      offStaticField_value(%eax),%ecx    # ecx<- lsw
2413    movl      4+offStaticField_value(%eax),%eax  # eax<- msw
2414    movzbl    rINST_HI,rINST_FULL                # rINST_FULL<- AA
2415    SET_VREG_WORD(%ecx,rINST_FULL,0)
2416    SET_VREG_WORD(%eax,rINST_FULL,1)
2417    FETCH_INST_WORD(2)
2418    ADVANCE_PC(2)
2419    GOTO_NEXT
2420
2421/* ------------------------------ */
2422    .balign 64
2423.L_OP_SGET_OBJECT: /* 0x62 */
2424/* File: x86/OP_SGET_OBJECT.S */
2425/* File: x86/OP_SGET.S */
2426    /*
2427     * General 32-bit SGET handler.
2428     *
2429     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2430     */
2431    /* op vAA, field@BBBB */
2432    GET_GLUE(%ecx)
2433    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2434    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2435    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2436    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2437    testl     %eax,%eax                          # resolved entry null?
2438    je        .LOP_SGET_OBJECT_resolve                # if not, make it so
2439.LOP_SGET_OBJECT_finish:     # field ptr in eax
2440    movl      offStaticField_value(%eax),%eax
2441    movzbl    rINST_HI,%ecx                      # ecx<- AA
2442    FETCH_INST_WORD(2)
2443    ADVANCE_PC(2)
2444    SET_VREG(%eax,%ecx)
2445    GOTO_NEXT
2446
2447
2448/* ------------------------------ */
2449    .balign 64
2450.L_OP_SGET_BOOLEAN: /* 0x63 */
2451/* File: x86/OP_SGET_BOOLEAN.S */
2452/* File: x86/OP_SGET.S */
2453    /*
2454     * General 32-bit SGET handler.
2455     *
2456     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2457     */
2458    /* op vAA, field@BBBB */
2459    GET_GLUE(%ecx)
2460    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2461    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2462    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2463    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2464    testl     %eax,%eax                          # resolved entry null?
2465    je        .LOP_SGET_BOOLEAN_resolve                # if not, make it so
2466.LOP_SGET_BOOLEAN_finish:     # field ptr in eax
2467    movl      offStaticField_value(%eax),%eax
2468    movzbl    rINST_HI,%ecx                      # ecx<- AA
2469    FETCH_INST_WORD(2)
2470    ADVANCE_PC(2)
2471    SET_VREG(%eax,%ecx)
2472    GOTO_NEXT
2473
2474
2475/* ------------------------------ */
2476    .balign 64
2477.L_OP_SGET_BYTE: /* 0x64 */
2478/* File: x86/OP_SGET_BYTE.S */
2479/* File: x86/OP_SGET.S */
2480    /*
2481     * General 32-bit SGET handler.
2482     *
2483     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2484     */
2485    /* op vAA, field@BBBB */
2486    GET_GLUE(%ecx)
2487    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2488    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2489    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2490    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2491    testl     %eax,%eax                          # resolved entry null?
2492    je        .LOP_SGET_BYTE_resolve                # if not, make it so
2493.LOP_SGET_BYTE_finish:     # field ptr in eax
2494    movl      offStaticField_value(%eax),%eax
2495    movzbl    rINST_HI,%ecx                      # ecx<- AA
2496    FETCH_INST_WORD(2)
2497    ADVANCE_PC(2)
2498    SET_VREG(%eax,%ecx)
2499    GOTO_NEXT
2500
2501
2502/* ------------------------------ */
2503    .balign 64
2504.L_OP_SGET_CHAR: /* 0x65 */
2505/* File: x86/OP_SGET_CHAR.S */
2506/* File: x86/OP_SGET.S */
2507    /*
2508     * General 32-bit SGET handler.
2509     *
2510     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2511     */
2512    /* op vAA, field@BBBB */
2513    GET_GLUE(%ecx)
2514    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2515    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2516    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2517    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2518    testl     %eax,%eax                          # resolved entry null?
2519    je        .LOP_SGET_CHAR_resolve                # if not, make it so
2520.LOP_SGET_CHAR_finish:     # field ptr in eax
2521    movl      offStaticField_value(%eax),%eax
2522    movzbl    rINST_HI,%ecx                      # ecx<- AA
2523    FETCH_INST_WORD(2)
2524    ADVANCE_PC(2)
2525    SET_VREG(%eax,%ecx)
2526    GOTO_NEXT
2527
2528
2529/* ------------------------------ */
2530    .balign 64
2531.L_OP_SGET_SHORT: /* 0x66 */
2532/* File: x86/OP_SGET_SHORT.S */
2533/* File: x86/OP_SGET.S */
2534    /*
2535     * General 32-bit SGET handler.
2536     *
2537     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2538     */
2539    /* op vAA, field@BBBB */
2540    GET_GLUE(%ecx)
2541    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2542    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2543    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2544    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2545    testl     %eax,%eax                          # resolved entry null?
2546    je        .LOP_SGET_SHORT_resolve                # if not, make it so
2547.LOP_SGET_SHORT_finish:     # field ptr in eax
2548    movl      offStaticField_value(%eax),%eax
2549    movzbl    rINST_HI,%ecx                      # ecx<- AA
2550    FETCH_INST_WORD(2)
2551    ADVANCE_PC(2)
2552    SET_VREG(%eax,%ecx)
2553    GOTO_NEXT
2554
2555
2556/* ------------------------------ */
2557    .balign 64
2558.L_OP_SPUT: /* 0x67 */
2559/* File: x86/OP_SPUT.S */
2560    /*
2561     * General 32-bit SPUT handler.
2562     *
2563     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2564     */
2565    /* op vAA, field@BBBB */
2566    GET_GLUE(%ecx)
2567    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2568    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2569    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2570    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2571    testl     %eax,%eax                          # resolved entry null?
2572    je        .LOP_SPUT_resolve                # if not, make it so
2573.LOP_SPUT_finish:     # field ptr in eax
2574    movzbl    rINST_HI,%ecx                      # ecx<- AA
2575    GET_VREG(%ecx,%ecx)
2576    FETCH_INST_WORD(2)
2577    movl      %ecx,offStaticField_value(%eax)
2578    ADVANCE_PC(2)
2579    GOTO_NEXT
2580
2581/* ------------------------------ */
2582    .balign 64
2583.L_OP_SPUT_WIDE: /* 0x68 */
2584/* File: x86/OP_SPUT_WIDE.S */
2585    /*
2586     * General 32-bit SPUT handler.
2587     *
2588     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2589     */
2590    /* op vAA, field@BBBB */
2591    GET_GLUE(%ecx)
2592    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2593    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2594    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2595    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2596    testl     %eax,%eax                          # resolved entry null?
2597    je        .LOP_SPUT_WIDE_resolve                # if not, make it so
2598.LOP_SPUT_WIDE_finish:     # field ptr in eax
2599    movzbl    rINST_HI,%ecx                      # ecx<- AA
2600    GET_VREG_WORD(rINST_FULL,%ecx,0)             # rINST_FULL<- lsw
2601    GET_VREG_WORD(%ecx,%ecx,1)                   # ecx<- msw
2602    movl      rINST_FULL,offStaticField_value(%eax)
2603    FETCH_INST_WORD(2)
2604    ADVANCE_PC(2)
2605    movl      %ecx,4+offStaticField_value(%eax)
2606    GOTO_NEXT
2607
2608/* ------------------------------ */
2609    .balign 64
2610.L_OP_SPUT_OBJECT: /* 0x69 */
2611/* File: x86/OP_SPUT_OBJECT.S */
2612/* File: x86/OP_SPUT.S */
2613    /*
2614     * General 32-bit SPUT handler.
2615     *
2616     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2617     */
2618    /* op vAA, field@BBBB */
2619    GET_GLUE(%ecx)
2620    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2621    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2622    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2623    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2624    testl     %eax,%eax                          # resolved entry null?
2625    je        .LOP_SPUT_OBJECT_resolve                # if not, make it so
2626.LOP_SPUT_OBJECT_finish:     # field ptr in eax
2627    movzbl    rINST_HI,%ecx                      # ecx<- AA
2628    GET_VREG(%ecx,%ecx)
2629    FETCH_INST_WORD(2)
2630    movl      %ecx,offStaticField_value(%eax)
2631    ADVANCE_PC(2)
2632    GOTO_NEXT
2633
2634
2635/* ------------------------------ */
2636    .balign 64
2637.L_OP_SPUT_BOOLEAN: /* 0x6a */
2638/* File: x86/OP_SPUT_BOOLEAN.S */
2639/* File: x86/OP_SPUT.S */
2640    /*
2641     * General 32-bit SPUT handler.
2642     *
2643     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2644     */
2645    /* op vAA, field@BBBB */
2646    GET_GLUE(%ecx)
2647    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2648    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2649    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2650    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2651    testl     %eax,%eax                          # resolved entry null?
2652    je        .LOP_SPUT_BOOLEAN_resolve                # if not, make it so
2653.LOP_SPUT_BOOLEAN_finish:     # field ptr in eax
2654    movzbl    rINST_HI,%ecx                      # ecx<- AA
2655    GET_VREG(%ecx,%ecx)
2656    FETCH_INST_WORD(2)
2657    movl      %ecx,offStaticField_value(%eax)
2658    ADVANCE_PC(2)
2659    GOTO_NEXT
2660
2661
2662/* ------------------------------ */
2663    .balign 64
2664.L_OP_SPUT_BYTE: /* 0x6b */
2665/* File: x86/OP_SPUT_BYTE.S */
2666/* File: x86/OP_SPUT.S */
2667    /*
2668     * General 32-bit SPUT handler.
2669     *
2670     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2671     */
2672    /* op vAA, field@BBBB */
2673    GET_GLUE(%ecx)
2674    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2675    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2676    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2677    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2678    testl     %eax,%eax                          # resolved entry null?
2679    je        .LOP_SPUT_BYTE_resolve                # if not, make it so
2680.LOP_SPUT_BYTE_finish:     # field ptr in eax
2681    movzbl    rINST_HI,%ecx                      # ecx<- AA
2682    GET_VREG(%ecx,%ecx)
2683    FETCH_INST_WORD(2)
2684    movl      %ecx,offStaticField_value(%eax)
2685    ADVANCE_PC(2)
2686    GOTO_NEXT
2687
2688
2689/* ------------------------------ */
2690    .balign 64
2691.L_OP_SPUT_CHAR: /* 0x6c */
2692/* File: x86/OP_SPUT_CHAR.S */
2693/* File: x86/OP_SPUT.S */
2694    /*
2695     * General 32-bit SPUT handler.
2696     *
2697     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2698     */
2699    /* op vAA, field@BBBB */
2700    GET_GLUE(%ecx)
2701    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2702    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2703    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2704    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2705    testl     %eax,%eax                          # resolved entry null?
2706    je        .LOP_SPUT_CHAR_resolve                # if not, make it so
2707.LOP_SPUT_CHAR_finish:     # field ptr in eax
2708    movzbl    rINST_HI,%ecx                      # ecx<- AA
2709    GET_VREG(%ecx,%ecx)
2710    FETCH_INST_WORD(2)
2711    movl      %ecx,offStaticField_value(%eax)
2712    ADVANCE_PC(2)
2713    GOTO_NEXT
2714
2715
2716/* ------------------------------ */
2717    .balign 64
2718.L_OP_SPUT_SHORT: /* 0x6d */
2719/* File: x86/OP_SPUT_SHORT.S */
2720/* File: x86/OP_SPUT.S */
2721    /*
2722     * General 32-bit SPUT handler.
2723     *
2724     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2725     */
2726    /* op vAA, field@BBBB */
2727    GET_GLUE(%ecx)
2728    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
2729    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
2730    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
2731    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
2732    testl     %eax,%eax                          # resolved entry null?
2733    je        .LOP_SPUT_SHORT_resolve                # if not, make it so
2734.LOP_SPUT_SHORT_finish:     # field ptr in eax
2735    movzbl    rINST_HI,%ecx                      # ecx<- AA
2736    GET_VREG(%ecx,%ecx)
2737    FETCH_INST_WORD(2)
2738    movl      %ecx,offStaticField_value(%eax)
2739    ADVANCE_PC(2)
2740    GOTO_NEXT
2741
2742
2743/* ------------------------------ */
2744    .balign 64
2745.L_OP_INVOKE_VIRTUAL: /* 0x6e */
2746/* File: x86/OP_INVOKE_VIRTUAL.S */
2747
2748    /*
2749     * Handle a virtual method call.
2750     *
2751     * for: invoke-virtual, invoke-virtual/range
2752     */
2753    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2754    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2755    GET_GLUE(%eax)
2756    movzwl    2(rPC),%ecx                 # ecx<- BBBB
2757    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
2758    EXPORT_PC()
2759    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
2760    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
2761    testl     %eax,%eax                   # already resolved?
2762    jne       .LOP_INVOKE_VIRTUAL_continue        # yes, continue
2763    GET_GLUE(%eax)
2764    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
2765    movl      offGlue_method(%eax),%eax   # eax<- glue->method
2766    SPILL(rPC)
2767    jmp       .LOP_INVOKE_VIRTUAL_more
2768
2769/* ------------------------------ */
2770    .balign 64
2771.L_OP_INVOKE_SUPER: /* 0x6f */
2772/* File: x86/OP_INVOKE_SUPER.S */
2773    /*
2774     * Handle a "super" method call.
2775     *
2776     * for: invoke-super, invoke-super/range
2777     */
2778    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2779    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2780    GET_GLUE(rINST_FULL)
2781    movzwl    2(rPC),%eax               # eax<- BBBB
2782    movl      offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
2783    EXPORT_PC()
2784    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
2785    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
2786    movl      offGlue_method(rINST_FULL),%eax # eax<- method
2787    movzwl    4(rPC),rINST_FULL         # rINST_FULL<- GFED or CCCC
2788    .if       (!0)
2789    andl      $0xf,rINST_FULL          # rINST_FULL<- D (or stays CCCC)
2790    .endif
2791    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- "this" ptr
2792    testl     rINST_FULL,rINST_FULL     # null "this"?
2793    je        common_errNullObject      # yes, throw
2794    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
2795    testl     %ecx,%ecx                 # already resolved?
2796    jne       .LOP_INVOKE_SUPER_continue      # yes - go on
2797    jmp       .LOP_INVOKE_SUPER_resolve
2798
2799/* ------------------------------ */
2800    .balign 64
2801.L_OP_INVOKE_DIRECT: /* 0x70 */
2802/* File: x86/OP_INVOKE_DIRECT.S */
2803    /*
2804     * Handle a direct method call.
2805     *
2806     * (We could defer the "is 'this' pointer null" test to the common
2807     * method invocation code, and use a flag to indicate that static
2808     * calls don't count.  If we do this as part of copying the arguments
2809     * out we could avoiding loading the first arg twice.)
2810     *
2811     * for: invoke-direct, invoke-direct/range
2812     */
2813    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2814    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2815    GET_GLUE(%ecx)
2816    movzwl    2(rPC),%eax              # eax<- BBBB
2817    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
2818    EXPORT_PC()
2819    SPILL(rPC)
2820    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
2821    movzwl    4(rPC),rPC               # rPC<- GFED or CCCC
2822    movl      (%ecx,%eax,4),%eax       # eax<- resolved methodToCall
2823    .if       (!0)
2824    andl      $0xf,rPC                # rPC<- D (or stays CCCC)
2825    .endif
2826    testl     %eax,%eax                # already resolved?
2827    GET_VREG(%ecx,rPC)                 # ecx<- "this" ptr
2828    je        .LOP_INVOKE_DIRECT_resolve      # not resolved, do it now
2829.LOP_INVOKE_DIRECT_finish:
2830    UNSPILL(rPC)
2831    testl     %ecx,%ecx                # null "this"?
2832    jne       common_invokeMethodNoRange  # no, continue on
2833    jmp       common_errNullObject
2834
2835/* ------------------------------ */
2836    .balign 64
2837.L_OP_INVOKE_STATIC: /* 0x71 */
2838/* File: x86/OP_INVOKE_STATIC.S */
2839    /*
2840     * Handle a static method call.
2841     *
2842     * for: invoke-static, invoke-static/range
2843     */
2844    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2845    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2846    GET_GLUE(%ecx)
2847    movzwl    2(rPC),%eax               # eax<- BBBB
2848    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
2849    EXPORT_PC()
2850    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
2851    movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
2852    testl     %eax,%eax
2853    jne       common_invokeMethodNoRange
2854    GET_GLUE(%ecx)
2855    movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
2856    movzwl    2(rPC),%eax
2857    movl      offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
2858    movl      %eax,OUT_ARG1(%esp)       # arg1<- BBBB
2859    movl      %ecx,OUT_ARG0(%esp)       # arg0<- clazz
2860    jmp       .LOP_INVOKE_STATIC_continue
2861
2862/* ------------------------------ */
2863    .balign 64
2864.L_OP_INVOKE_INTERFACE: /* 0x72 */
2865/* File: x86/OP_INVOKE_INTERFACE.S */
2866    /*
2867     * Handle an interface method call.
2868     *
2869     * for: invoke-interface, invoke-interface/range
2870     */
2871    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2872    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2873    movzwl     4(rPC),%eax              # eax<- FEDC or CCCC
2874    GET_GLUE(%ecx)
2875    .if        (!0)
2876    andl       $0xf,%eax               # eax<- C (or stays CCCC)
2877    .endif
2878    GET_VREG(%eax,%eax)                 # eax<- "this"
2879    EXPORT_PC()
2880    testl      %eax,%eax                # null this?
2881    je         common_errNullObject     # yes, fail
2882    movl       offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
2883    movl       %eax,OUT_ARG0(%esp)                 # arg0<- class
2884    movl       offGlue_methodClassDex(%ecx),%eax   # eax<- methodClassDex
2885    movl       offGlue_method(%ecx),%ecx           # ecx<- method
2886    movl       %eax,OUT_ARG3(%esp)                 # arg3<- dex
2887    movzwl     2(rPC),%eax                         # eax<- BBBB
2888    movl       %ecx,OUT_ARG2(%esp)                 # arg2<- method
2889    movl       %eax,OUT_ARG1(%esp)                 # arg1<- BBBB
2890    SPILL(rPC)
2891    jmp        .LOP_INVOKE_INTERFACE_continue
2892
2893/* ------------------------------ */
2894    .balign 64
2895.L_OP_UNUSED_73: /* 0x73 */
2896/* File: x86/OP_UNUSED_73.S */
2897/* File: x86/unused.S */
2898    jmp     common_abort
2899
2900
2901/* ------------------------------ */
2902    .balign 64
2903.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
2904/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */
2905/* File: x86/OP_INVOKE_VIRTUAL.S */
2906
2907    /*
2908     * Handle a virtual method call.
2909     *
2910     * for: invoke-virtual, invoke-virtual/range
2911     */
2912    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2913    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2914    GET_GLUE(%eax)
2915    movzwl    2(rPC),%ecx                 # ecx<- BBBB
2916    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
2917    EXPORT_PC()
2918    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
2919    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
2920    testl     %eax,%eax                   # already resolved?
2921    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # yes, continue
2922    GET_GLUE(%eax)
2923    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
2924    movl      offGlue_method(%eax),%eax   # eax<- glue->method
2925    SPILL(rPC)
2926    jmp       .LOP_INVOKE_VIRTUAL_RANGE_more
2927
2928
2929/* ------------------------------ */
2930    .balign 64
2931.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
2932/* File: x86/OP_INVOKE_SUPER_RANGE.S */
2933/* File: x86/OP_INVOKE_SUPER.S */
2934    /*
2935     * Handle a "super" method call.
2936     *
2937     * for: invoke-super, invoke-super/range
2938     */
2939    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2940    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2941    GET_GLUE(rINST_FULL)
2942    movzwl    2(rPC),%eax               # eax<- BBBB
2943    movl      offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
2944    EXPORT_PC()
2945    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
2946    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
2947    movl      offGlue_method(rINST_FULL),%eax # eax<- method
2948    movzwl    4(rPC),rINST_FULL         # rINST_FULL<- GFED or CCCC
2949    .if       (!1)
2950    andl      $0xf,rINST_FULL          # rINST_FULL<- D (or stays CCCC)
2951    .endif
2952    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- "this" ptr
2953    testl     rINST_FULL,rINST_FULL     # null "this"?
2954    je        common_errNullObject      # yes, throw
2955    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
2956    testl     %ecx,%ecx                 # already resolved?
2957    jne       .LOP_INVOKE_SUPER_RANGE_continue      # yes - go on
2958    jmp       .LOP_INVOKE_SUPER_RANGE_resolve
2959
2960
2961/* ------------------------------ */
2962    .balign 64
2963.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
2964/* File: x86/OP_INVOKE_DIRECT_RANGE.S */
2965/* File: x86/OP_INVOKE_DIRECT.S */
2966    /*
2967     * Handle a direct method call.
2968     *
2969     * (We could defer the "is 'this' pointer null" test to the common
2970     * method invocation code, and use a flag to indicate that static
2971     * calls don't count.  If we do this as part of copying the arguments
2972     * out we could avoiding loading the first arg twice.)
2973     *
2974     * for: invoke-direct, invoke-direct/range
2975     */
2976    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
2977    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
2978    GET_GLUE(%ecx)
2979    movzwl    2(rPC),%eax              # eax<- BBBB
2980    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
2981    EXPORT_PC()
2982    SPILL(rPC)
2983    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
2984    movzwl    4(rPC),rPC               # rPC<- GFED or CCCC
2985    movl      (%ecx,%eax,4),%eax       # eax<- resolved methodToCall
2986    .if       (!1)
2987    andl      $0xf,rPC                # rPC<- D (or stays CCCC)
2988    .endif
2989    testl     %eax,%eax                # already resolved?
2990    GET_VREG(%ecx,rPC)                 # ecx<- "this" ptr
2991    je        .LOP_INVOKE_DIRECT_RANGE_resolve      # not resolved, do it now
2992.LOP_INVOKE_DIRECT_RANGE_finish:
2993    UNSPILL(rPC)
2994    testl     %ecx,%ecx                # null "this"?
2995    jne       common_invokeMethodRange  # no, continue on
2996    jmp       common_errNullObject
2997
2998
2999/* ------------------------------ */
3000    .balign 64
3001.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3002/* File: x86/OP_INVOKE_STATIC_RANGE.S */
3003/* File: x86/OP_INVOKE_STATIC.S */
3004    /*
3005     * Handle a static method call.
3006     *
3007     * for: invoke-static, invoke-static/range
3008     */
3009    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3010    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3011    GET_GLUE(%ecx)
3012    movzwl    2(rPC),%eax               # eax<- BBBB
3013    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
3014    EXPORT_PC()
3015    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
3016    movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
3017    testl     %eax,%eax
3018    jne       common_invokeMethodRange
3019    GET_GLUE(%ecx)
3020    movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
3021    movzwl    2(rPC),%eax
3022    movl      offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
3023    movl      %eax,OUT_ARG1(%esp)       # arg1<- BBBB
3024    movl      %ecx,OUT_ARG0(%esp)       # arg0<- clazz
3025    jmp       .LOP_INVOKE_STATIC_RANGE_continue
3026
3027
3028/* ------------------------------ */
3029    .balign 64
3030.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3031/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */
3032/* File: x86/OP_INVOKE_INTERFACE.S */
3033    /*
3034     * Handle an interface method call.
3035     *
3036     * for: invoke-interface, invoke-interface/range
3037     */
3038    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3039    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3040    movzwl     4(rPC),%eax              # eax<- FEDC or CCCC
3041    GET_GLUE(%ecx)
3042    .if        (!1)
3043    andl       $0xf,%eax               # eax<- C (or stays CCCC)
3044    .endif
3045    GET_VREG(%eax,%eax)                 # eax<- "this"
3046    EXPORT_PC()
3047    testl      %eax,%eax                # null this?
3048    je         common_errNullObject     # yes, fail
3049    movl       offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
3050    movl       %eax,OUT_ARG0(%esp)                 # arg0<- class
3051    movl       offGlue_methodClassDex(%ecx),%eax   # eax<- methodClassDex
3052    movl       offGlue_method(%ecx),%ecx           # ecx<- method
3053    movl       %eax,OUT_ARG3(%esp)                 # arg3<- dex
3054    movzwl     2(rPC),%eax                         # eax<- BBBB
3055    movl       %ecx,OUT_ARG2(%esp)                 # arg2<- method
3056    movl       %eax,OUT_ARG1(%esp)                 # arg1<- BBBB
3057    SPILL(rPC)
3058    jmp        .LOP_INVOKE_INTERFACE_RANGE_continue
3059
3060
3061/* ------------------------------ */
3062    .balign 64
3063.L_OP_UNUSED_79: /* 0x79 */
3064/* File: x86/OP_UNUSED_79.S */
3065/* File: x86/unused.S */
3066    jmp     common_abort
3067
3068
3069/* ------------------------------ */
3070    .balign 64
3071.L_OP_UNUSED_7A: /* 0x7a */
3072/* File: x86/OP_UNUSED_7A.S */
3073/* File: x86/unused.S */
3074    jmp     common_abort
3075
3076
3077/* ------------------------------ */
3078    .balign 64
3079.L_OP_NEG_INT: /* 0x7b */
3080/* File: x86/OP_NEG_INT.S */
3081/* File: x86/unop.S */
3082    /*
3083     * Generic 32-bit unary operation.  Provide an "instr" line that
3084     * specifies an instruction that performs "result = op eax".
3085     */
3086    /* unop vA, vB */
3087    movzbl   rINST_HI,%ecx           # ecx<- A+
3088    sarl     $12,rINST_FULL         # rINST_FULL<- B
3089    GET_VREG(%eax,rINST_FULL)        # eax<- vB
3090    andb     $0xf,%cl               # ecx<- A
3091    FETCH_INST_WORD(1)
3092    ADVANCE_PC(1)
3093
3094
3095    negl %eax
3096    SET_VREG(%eax,%ecx)
3097    GOTO_NEXT
3098
3099
3100/* ------------------------------ */
3101    .balign 64
3102.L_OP_NOT_INT: /* 0x7c */
3103/* File: x86/OP_NOT_INT.S */
3104/* File: x86/unop.S */
3105    /*
3106     * Generic 32-bit unary operation.  Provide an "instr" line that
3107     * specifies an instruction that performs "result = op eax".
3108     */
3109    /* unop vA, vB */
3110    movzbl   rINST_HI,%ecx           # ecx<- A+
3111    sarl     $12,rINST_FULL         # rINST_FULL<- B
3112    GET_VREG(%eax,rINST_FULL)        # eax<- vB
3113    andb     $0xf,%cl               # ecx<- A
3114    FETCH_INST_WORD(1)
3115    ADVANCE_PC(1)
3116
3117
3118    notl %eax
3119    SET_VREG(%eax,%ecx)
3120    GOTO_NEXT
3121
3122
3123/* ------------------------------ */
3124    .balign 64
3125.L_OP_NEG_LONG: /* 0x7d */
3126/* File: x86/OP_NEG_LONG.S */
3127    /* unop vA, vB */
3128    movzbl    rINST_HI,%ecx            # ecx<- BA
3129    sarl      $4,%ecx                 # ecx<- B
3130    movzbl    rINST_HI,rINST_FULL      # ecx<- BA
3131    andb      $0xf,rINST_LO           # rINST_FULL<- A
3132    GET_VREG_WORD(%eax,%ecx,0)         # eax<- v[B+0]
3133    GET_VREG_WORD(%ecx,%ecx,1)         # ecx<- v[B+1]
3134    negl      %eax
3135    adcl      $0,%ecx
3136    negl      %ecx
3137    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[A+0]<- eax
3138    SET_VREG_WORD(%ecx,rINST_FULL,1)   # v[A+1]<- ecx
3139    FETCH_INST_WORD(1)
3140    ADVANCE_PC(1)
3141    GOTO_NEXT
3142
3143/* ------------------------------ */
3144    .balign 64
3145.L_OP_NOT_LONG: /* 0x7e */
3146/* File: x86/OP_NOT_LONG.S */
3147    /* unop vA, vB */
3148    movzbl    rINST_HI,%ecx            # ecx<- BA
3149    sarl      $4,%ecx                 # ecx<- B
3150    movzbl    rINST_HI,rINST_FULL      # ecx<- BA
3151    andb      $0xf,rINST_LO           # rINST_FULL<- A
3152    GET_VREG_WORD(%eax,%ecx,0)         # eax<- v[B+0]
3153    GET_VREG_WORD(%ecx,%ecx,1)         # ecx<- v[B+1]
3154    notl      %eax
3155    notl      %ecx
3156    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[A+0]<- eax
3157    SET_VREG_WORD(%ecx,rINST_FULL,1)   # v[A+1]<- ecx
3158    FETCH_INST_WORD(1)
3159    ADVANCE_PC(1)
3160    GOTO_NEXT
3161
3162/* ------------------------------ */
3163    .balign 64
3164.L_OP_NEG_FLOAT: /* 0x7f */
3165/* File: x86/OP_NEG_FLOAT.S */
3166/* File: x86/fpcvt.S */
3167    /*
3168     * Generic 32-bit FP conversion operation.
3169     */
3170    /* unop vA, vB */
3171    movzbl   rINST_HI,%ecx           # ecx<- A+
3172    sarl     $12,rINST_FULL         # rINST_FULL<- B
3173    flds    (rFP,rINST_FULL,4)      # %st0<- vB
3174    andb     $0xf,%cl               # ecx<- A
3175    FETCH_INST_WORD(1)
3176    ADVANCE_PC(1)
3177    fchs
3178    fstps  (rFP,%ecx,4)             # vA<- %st0
3179    GOTO_NEXT
3180
3181
3182/* ------------------------------ */
3183    .balign 64
3184.L_OP_NEG_DOUBLE: /* 0x80 */
3185/* File: x86/OP_NEG_DOUBLE.S */
3186/* File: x86/fpcvt.S */
3187    /*
3188     * Generic 32-bit FP conversion operation.
3189     */
3190    /* unop vA, vB */
3191    movzbl   rINST_HI,%ecx           # ecx<- A+
3192    sarl     $12,rINST_FULL         # rINST_FULL<- B
3193    fldl    (rFP,rINST_FULL,4)      # %st0<- vB
3194    andb     $0xf,%cl               # ecx<- A
3195    FETCH_INST_WORD(1)
3196    ADVANCE_PC(1)
3197    fchs
3198    fstpl  (rFP,%ecx,4)             # vA<- %st0
3199    GOTO_NEXT
3200
3201
3202/* ------------------------------ */
3203    .balign 64
3204.L_OP_INT_TO_LONG: /* 0x81 */
3205/* File: x86/OP_INT_TO_LONG.S */
3206    /* int to long vA, vB */
3207    movzbl  rINST_HI,%ecx               # ecx<- +A
3208    sarl    $12,rINST_FULL             # rINST_FULL<- B
3209    GET_VREG(%eax,rINST_FULL)           # eax<- vB
3210    SPILL(rPC)                          # will step on edx later
3211    andb    $0xf,%cl                   # ecx<- A
3212    cltd                                # edx:eax<- sssssssBBBBBBBB
3213    SET_VREG_WORD(%edx,%ecx,1)          # v[A+1]<- edx/rPC
3214    UNSPILL(rPC)
3215    SET_VREG_WORD(%eax,%ecx,0)          # v[A+0]<- %eax
3216    FETCH_INST_WORD(1)
3217    ADVANCE_PC(1)
3218    GOTO_NEXT
3219
3220/* ------------------------------ */
3221    .balign 64
3222.L_OP_INT_TO_FLOAT: /* 0x82 */
3223/* File: x86/OP_INT_TO_FLOAT.S */
3224/* File: x86/fpcvt.S */
3225    /*
3226     * Generic 32-bit FP conversion operation.
3227     */
3228    /* unop vA, vB */
3229    movzbl   rINST_HI,%ecx           # ecx<- A+
3230    sarl     $12,rINST_FULL         # rINST_FULL<- B
3231    fildl    (rFP,rINST_FULL,4)      # %st0<- vB
3232    andb     $0xf,%cl               # ecx<- A
3233    FETCH_INST_WORD(1)
3234    ADVANCE_PC(1)
3235
3236    fstps  (rFP,%ecx,4)             # vA<- %st0
3237    GOTO_NEXT
3238
3239
3240/* ------------------------------ */
3241    .balign 64
3242.L_OP_INT_TO_DOUBLE: /* 0x83 */
3243/* File: x86/OP_INT_TO_DOUBLE.S */
3244/* File: x86/fpcvt.S */
3245    /*
3246     * Generic 32-bit FP conversion operation.
3247     */
3248    /* unop vA, vB */
3249    movzbl   rINST_HI,%ecx           # ecx<- A+
3250    sarl     $12,rINST_FULL         # rINST_FULL<- B
3251    fildl    (rFP,rINST_FULL,4)      # %st0<- vB
3252    andb     $0xf,%cl               # ecx<- A
3253    FETCH_INST_WORD(1)
3254    ADVANCE_PC(1)
3255
3256    fstpl  (rFP,%ecx,4)             # vA<- %st0
3257    GOTO_NEXT
3258
3259
3260/* ------------------------------ */
3261    .balign 64
3262.L_OP_LONG_TO_INT: /* 0x84 */
3263/* File: x86/OP_LONG_TO_INT.S */
3264/* we ignore the high word, making this equivalent to a 32-bit reg move */
3265/* File: x86/OP_MOVE.S */
3266    /* for move, move-object, long-to-int */
3267    /* op vA, vB */
3268    movzbl rINST_HI,%eax         # eax<- BA
3269    andb   $0xf,%al             # eax<- A
3270    shrl   $12,rINST_FULL       # rINST_FULL<- B
3271    GET_VREG(%ecx,rINST_FULL)
3272    FETCH_INST_WORD(1)
3273    ADVANCE_PC(1)
3274    SET_VREG(%ecx,%eax)          # fp[A]<-fp[B]
3275    GOTO_NEXT
3276
3277
3278/* ------------------------------ */
3279    .balign 64
3280.L_OP_LONG_TO_FLOAT: /* 0x85 */
3281/* File: x86/OP_LONG_TO_FLOAT.S */
3282/* File: x86/fpcvt.S */
3283    /*
3284     * Generic 32-bit FP conversion operation.
3285     */
3286    /* unop vA, vB */
3287    movzbl   rINST_HI,%ecx           # ecx<- A+
3288    sarl     $12,rINST_FULL         # rINST_FULL<- B
3289    fildll    (rFP,rINST_FULL,4)      # %st0<- vB
3290    andb     $0xf,%cl               # ecx<- A
3291    FETCH_INST_WORD(1)
3292    ADVANCE_PC(1)
3293
3294    fstps  (rFP,%ecx,4)             # vA<- %st0
3295    GOTO_NEXT
3296
3297
3298/* ------------------------------ */
3299    .balign 64
3300.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3301/* File: x86/OP_LONG_TO_DOUBLE.S */
3302/* File: x86/fpcvt.S */
3303    /*
3304     * Generic 32-bit FP conversion operation.
3305     */
3306    /* unop vA, vB */
3307    movzbl   rINST_HI,%ecx           # ecx<- A+
3308    sarl     $12,rINST_FULL         # rINST_FULL<- B
3309    fildll    (rFP,rINST_FULL,4)      # %st0<- vB
3310    andb     $0xf,%cl               # ecx<- A
3311    FETCH_INST_WORD(1)
3312    ADVANCE_PC(1)
3313
3314    fstpl  (rFP,%ecx,4)             # vA<- %st0
3315    GOTO_NEXT
3316
3317
3318/* ------------------------------ */
3319    .balign 64
3320.L_OP_FLOAT_TO_INT: /* 0x87 */
3321/* File: x86/OP_FLOAT_TO_INT.S */
3322/* File: x86/cvtfp_int.S */
3323/* On fp to int conversions, Java requires that
3324 * if the result > maxint, it should be clamped to maxint.  If it is less
3325 * than minint, it should be clamped to minint.  If it is a nan, the result
3326 * should be zero.  Further, the rounding mode is to truncate.  This model
3327 * differs from what is delivered normally via the x86 fpu, so we have
3328 * to play some games.
3329 */
3330    /* float/double to int/long vA, vB */
3331    movzbl    rINST_HI,%ecx           # ecx<- A+
3332    sarl      $12,rINST_FULL         # rINST_FULL<- B
3333    .if 0
3334    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
3335    .else
3336    flds     (rFP,rINST_FULL,4)       # %st0<- vB
3337    .endif
3338    ftst
3339    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3340    movzwl   LOCAL0_OFFSET(%ebp),%eax
3341    movb     $0xc,%ah
3342    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3343    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
3344    FETCH_INST_WORD(1)
3345    andb     $0xf,%cl                # ecx<- A
3346    .if 0
3347    fistpll  (rFP,%ecx,4)             # convert and store
3348    .else
3349    fistpl   (rFP,%ecx,4)             # convert and store
3350    .endif
3351    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3352    jmp      .LOP_FLOAT_TO_INT_continue
3353
3354
3355/* ------------------------------ */
3356    .balign 64
3357.L_OP_FLOAT_TO_LONG: /* 0x88 */
3358/* File: x86/OP_FLOAT_TO_LONG.S */
3359/* File: x86/cvtfp_int.S */
3360/* On fp to int conversions, Java requires that
3361 * if the result > maxint, it should be clamped to maxint.  If it is less
3362 * than minint, it should be clamped to minint.  If it is a nan, the result
3363 * should be zero.  Further, the rounding mode is to truncate.  This model
3364 * differs from what is delivered normally via the x86 fpu, so we have
3365 * to play some games.
3366 */
3367    /* float/double to int/long vA, vB */
3368    movzbl    rINST_HI,%ecx           # ecx<- A+
3369    sarl      $12,rINST_FULL         # rINST_FULL<- B
3370    .if 0
3371    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
3372    .else
3373    flds     (rFP,rINST_FULL,4)       # %st0<- vB
3374    .endif
3375    ftst
3376    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3377    movzwl   LOCAL0_OFFSET(%ebp),%eax
3378    movb     $0xc,%ah
3379    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3380    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
3381    FETCH_INST_WORD(1)
3382    andb     $0xf,%cl                # ecx<- A
3383    .if 1
3384    fistpll  (rFP,%ecx,4)             # convert and store
3385    .else
3386    fistpl   (rFP,%ecx,4)             # convert and store
3387    .endif
3388    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3389    jmp      .LOP_FLOAT_TO_LONG_continue
3390
3391
3392/* ------------------------------ */
3393    .balign 64
3394.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3395/* File: x86/OP_FLOAT_TO_DOUBLE.S */
3396/* File: x86/fpcvt.S */
3397    /*
3398     * Generic 32-bit FP conversion operation.
3399     */
3400    /* unop vA, vB */
3401    movzbl   rINST_HI,%ecx           # ecx<- A+
3402    sarl     $12,rINST_FULL         # rINST_FULL<- B
3403    flds    (rFP,rINST_FULL,4)      # %st0<- vB
3404    andb     $0xf,%cl               # ecx<- A
3405    FETCH_INST_WORD(1)
3406    ADVANCE_PC(1)
3407
3408    fstpl  (rFP,%ecx,4)             # vA<- %st0
3409    GOTO_NEXT
3410
3411
3412/* ------------------------------ */
3413    .balign 64
3414.L_OP_DOUBLE_TO_INT: /* 0x8a */
3415/* File: x86/OP_DOUBLE_TO_INT.S */
3416/* File: x86/cvtfp_int.S */
3417/* On fp to int conversions, Java requires that
3418 * if the result > maxint, it should be clamped to maxint.  If it is less
3419 * than minint, it should be clamped to minint.  If it is a nan, the result
3420 * should be zero.  Further, the rounding mode is to truncate.  This model
3421 * differs from what is delivered normally via the x86 fpu, so we have
3422 * to play some games.
3423 */
3424    /* float/double to int/long vA, vB */
3425    movzbl    rINST_HI,%ecx           # ecx<- A+
3426    sarl      $12,rINST_FULL         # rINST_FULL<- B
3427    .if 1
3428    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
3429    .else
3430    flds     (rFP,rINST_FULL,4)       # %st0<- vB
3431    .endif
3432    ftst
3433    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3434    movzwl   LOCAL0_OFFSET(%ebp),%eax
3435    movb     $0xc,%ah
3436    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3437    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
3438    FETCH_INST_WORD(1)
3439    andb     $0xf,%cl                # ecx<- A
3440    .if 0
3441    fistpll  (rFP,%ecx,4)             # convert and store
3442    .else
3443    fistpl   (rFP,%ecx,4)             # convert and store
3444    .endif
3445    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3446    jmp      .LOP_DOUBLE_TO_INT_continue
3447
3448
3449/* ------------------------------ */
3450    .balign 64
3451.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3452/* File: x86/OP_DOUBLE_TO_LONG.S */
3453/* File: x86/cvtfp_int.S */
3454/* On fp to int conversions, Java requires that
3455 * if the result > maxint, it should be clamped to maxint.  If it is less
3456 * than minint, it should be clamped to minint.  If it is a nan, the result
3457 * should be zero.  Further, the rounding mode is to truncate.  This model
3458 * differs from what is delivered normally via the x86 fpu, so we have
3459 * to play some games.
3460 */
3461    /* float/double to int/long vA, vB */
3462    movzbl    rINST_HI,%ecx           # ecx<- A+
3463    sarl      $12,rINST_FULL         # rINST_FULL<- B
3464    .if 1
3465    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
3466    .else
3467    flds     (rFP,rINST_FULL,4)       # %st0<- vB
3468    .endif
3469    ftst
3470    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
3471    movzwl   LOCAL0_OFFSET(%ebp),%eax
3472    movb     $0xc,%ah
3473    movw     %ax,LOCAL0_OFFSET+2(%ebp)
3474    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
3475    FETCH_INST_WORD(1)
3476    andb     $0xf,%cl                # ecx<- A
3477    .if 1
3478    fistpll  (rFP,%ecx,4)             # convert and store
3479    .else
3480    fistpl   (rFP,%ecx,4)             # convert and store
3481    .endif
3482    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
3483    jmp      .LOP_DOUBLE_TO_LONG_continue
3484
3485
3486/* ------------------------------ */
3487    .balign 64
3488.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3489/* File: x86/OP_DOUBLE_TO_FLOAT.S */
3490/* File: x86/fpcvt.S */
3491    /*
3492     * Generic 32-bit FP conversion operation.
3493     */
3494    /* unop vA, vB */
3495    movzbl   rINST_HI,%ecx           # ecx<- A+
3496    sarl     $12,rINST_FULL         # rINST_FULL<- B
3497    fldl    (rFP,rINST_FULL,4)      # %st0<- vB
3498    andb     $0xf,%cl               # ecx<- A
3499    FETCH_INST_WORD(1)
3500    ADVANCE_PC(1)
3501
3502    fstps  (rFP,%ecx,4)             # vA<- %st0
3503    GOTO_NEXT
3504
3505
3506/* ------------------------------ */
3507    .balign 64
3508.L_OP_INT_TO_BYTE: /* 0x8d */
3509/* File: x86/OP_INT_TO_BYTE.S */
3510/* File: x86/unop.S */
3511    /*
3512     * Generic 32-bit unary operation.  Provide an "instr" line that
3513     * specifies an instruction that performs "result = op eax".
3514     */
3515    /* unop vA, vB */
3516    movzbl   rINST_HI,%ecx           # ecx<- A+
3517    sarl     $12,rINST_FULL         # rINST_FULL<- B
3518    GET_VREG(%eax,rINST_FULL)        # eax<- vB
3519    andb     $0xf,%cl               # ecx<- A
3520    FETCH_INST_WORD(1)
3521    ADVANCE_PC(1)
3522
3523
3524    movsbl %al,%eax
3525    SET_VREG(%eax,%ecx)
3526    GOTO_NEXT
3527
3528
3529/* ------------------------------ */
3530    .balign 64
3531.L_OP_INT_TO_CHAR: /* 0x8e */
3532/* File: x86/OP_INT_TO_CHAR.S */
3533/* File: x86/unop.S */
3534    /*
3535     * Generic 32-bit unary operation.  Provide an "instr" line that
3536     * specifies an instruction that performs "result = op eax".
3537     */
3538    /* unop vA, vB */
3539    movzbl   rINST_HI,%ecx           # ecx<- A+
3540    sarl     $12,rINST_FULL         # rINST_FULL<- B
3541    GET_VREG(%eax,rINST_FULL)        # eax<- vB
3542    andb     $0xf,%cl               # ecx<- A
3543    FETCH_INST_WORD(1)
3544    ADVANCE_PC(1)
3545
3546
3547    movzwl %ax,%eax
3548    SET_VREG(%eax,%ecx)
3549    GOTO_NEXT
3550
3551
3552/* ------------------------------ */
3553    .balign 64
3554.L_OP_INT_TO_SHORT: /* 0x8f */
3555/* File: x86/OP_INT_TO_SHORT.S */
3556/* File: x86/unop.S */
3557    /*
3558     * Generic 32-bit unary operation.  Provide an "instr" line that
3559     * specifies an instruction that performs "result = op eax".
3560     */
3561    /* unop vA, vB */
3562    movzbl   rINST_HI,%ecx           # ecx<- A+
3563    sarl     $12,rINST_FULL         # rINST_FULL<- B
3564    GET_VREG(%eax,rINST_FULL)        # eax<- vB
3565    andb     $0xf,%cl               # ecx<- A
3566    FETCH_INST_WORD(1)
3567    ADVANCE_PC(1)
3568
3569
3570    movswl %ax,%eax
3571    SET_VREG(%eax,%ecx)
3572    GOTO_NEXT
3573
3574
3575/* ------------------------------ */
3576    .balign 64
3577.L_OP_ADD_INT: /* 0x90 */
3578/* File: x86/OP_ADD_INT.S */
3579/* File: x86/binop.S */
3580    /*
3581     * Generic 32-bit binary operation.  Provide an "instr" line that
3582     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3583     * This could be an x86 instruction or a function call.  (If the result
3584     * comes back in a register other than eax, you can override "result".)
3585     *
3586     * For: add-int, sub-int, and-int, or-int,
3587     *      xor-int, shl-int, shr-int, ushr-int
3588     */
3589    /* binop vAA, vBB, vCC */
3590    movzbl   2(rPC),%eax            # eax<- BB
3591    movzbl   3(rPC),%ecx            # ecx<- CC
3592    GET_VREG(%eax,%eax)             # eax<- vBB
3593    addl (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
3594    movzbl   rINST_HI,%ecx         # ecx<- AA
3595    FETCH_INST_WORD(2)
3596    ADVANCE_PC(2)
3597    SET_VREG(%eax,%ecx)
3598    GOTO_NEXT
3599
3600
3601/* ------------------------------ */
3602    .balign 64
3603.L_OP_SUB_INT: /* 0x91 */
3604/* File: x86/OP_SUB_INT.S */
3605/* File: x86/binop.S */
3606    /*
3607     * Generic 32-bit binary operation.  Provide an "instr" line that
3608     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3609     * This could be an x86 instruction or a function call.  (If the result
3610     * comes back in a register other than eax, you can override "result".)
3611     *
3612     * For: add-int, sub-int, and-int, or-int,
3613     *      xor-int, shl-int, shr-int, ushr-int
3614     */
3615    /* binop vAA, vBB, vCC */
3616    movzbl   2(rPC),%eax            # eax<- BB
3617    movzbl   3(rPC),%ecx            # ecx<- CC
3618    GET_VREG(%eax,%eax)             # eax<- vBB
3619    subl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
3620    movzbl   rINST_HI,%ecx         # ecx<- AA
3621    FETCH_INST_WORD(2)
3622    ADVANCE_PC(2)
3623    SET_VREG(%eax,%ecx)
3624    GOTO_NEXT
3625
3626
3627/* ------------------------------ */
3628    .balign 64
3629.L_OP_MUL_INT: /* 0x92 */
3630/* File: x86/OP_MUL_INT.S */
3631    /*
3632     * 32-bit binary multiplication.
3633     */
3634    /* mul vAA, vBB, vCC */
3635    movzbl   2(rPC),%eax            # eax<- BB
3636    movzbl   3(rPC),%ecx            # ecx<- CC
3637    SPILL(rPC)
3638    GET_VREG(%eax,%eax)             # eax<- vBB
3639    imull    (rFP,%ecx,4),%eax      # trashes rPC/edx
3640    UNSPILL(rPC)
3641    movzbl   rINST_HI,%ecx          # ecx<- AA
3642    FETCH_INST_WORD(2)
3643    ADVANCE_PC(2)
3644    SET_VREG(%eax,%ecx)
3645    GOTO_NEXT
3646
3647/* ------------------------------ */
3648    .balign 64
3649.L_OP_DIV_INT: /* 0x93 */
3650/* File: x86/OP_DIV_INT.S */
3651/* File: x86/bindiv.S */
3652
3653    /*
3654     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
3655     * op1=-1.
3656     */
3657    /* binop vAA, vBB, vCC */
3658    movzbl   2(rPC),%eax            # eax<- BB
3659    movzbl   3(rPC),%ecx            # ecx<- CC
3660    GET_VREG(%eax,%eax)             # eax<- vBB
3661    GET_VREG(%ecx,%ecx)             # eax<- vBB
3662    SPILL(rPC)
3663    cmpl     $0,%ecx
3664    je       common_errDivideByZero
3665    cmpl     $-1,%ecx
3666    jne      .LOP_DIV_INT_continue_div
3667    cmpl     $0x80000000,%eax
3668    jne      .LOP_DIV_INT_continue_div
3669    movl     $0x80000000,%eax
3670    jmp      .LOP_DIV_INT_finish_div
3671
3672
3673
3674/* ------------------------------ */
3675    .balign 64
3676.L_OP_REM_INT: /* 0x94 */
3677/* File: x86/OP_REM_INT.S */
3678/* File: x86/bindiv.S */
3679
3680    /*
3681     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
3682     * op1=-1.
3683     */
3684    /* binop vAA, vBB, vCC */
3685    movzbl   2(rPC),%eax            # eax<- BB
3686    movzbl   3(rPC),%ecx            # ecx<- CC
3687    GET_VREG(%eax,%eax)             # eax<- vBB
3688    GET_VREG(%ecx,%ecx)             # eax<- vBB
3689    SPILL(rPC)
3690    cmpl     $0,%ecx
3691    je       common_errDivideByZero
3692    cmpl     $-1,%ecx
3693    jne      .LOP_REM_INT_continue_div
3694    cmpl     $0x80000000,%eax
3695    jne      .LOP_REM_INT_continue_div
3696    movl     $0,%edx
3697    jmp      .LOP_REM_INT_finish_div
3698
3699
3700
3701/* ------------------------------ */
3702    .balign 64
3703.L_OP_AND_INT: /* 0x95 */
3704/* File: x86/OP_AND_INT.S */
3705/* File: x86/binop.S */
3706    /*
3707     * Generic 32-bit binary operation.  Provide an "instr" line that
3708     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3709     * This could be an x86 instruction or a function call.  (If the result
3710     * comes back in a register other than eax, you can override "result".)
3711     *
3712     * For: add-int, sub-int, and-int, or-int,
3713     *      xor-int, shl-int, shr-int, ushr-int
3714     */
3715    /* binop vAA, vBB, vCC */
3716    movzbl   2(rPC),%eax            # eax<- BB
3717    movzbl   3(rPC),%ecx            # ecx<- CC
3718    GET_VREG(%eax,%eax)             # eax<- vBB
3719    andl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
3720    movzbl   rINST_HI,%ecx         # ecx<- AA
3721    FETCH_INST_WORD(2)
3722    ADVANCE_PC(2)
3723    SET_VREG(%eax,%ecx)
3724    GOTO_NEXT
3725
3726
3727/* ------------------------------ */
3728    .balign 64
3729.L_OP_OR_INT: /* 0x96 */
3730/* File: x86/OP_OR_INT.S */
3731/* File: x86/binop.S */
3732    /*
3733     * Generic 32-bit binary operation.  Provide an "instr" line that
3734     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3735     * This could be an x86 instruction or a function call.  (If the result
3736     * comes back in a register other than eax, you can override "result".)
3737     *
3738     * For: add-int, sub-int, and-int, or-int,
3739     *      xor-int, shl-int, shr-int, ushr-int
3740     */
3741    /* binop vAA, vBB, vCC */
3742    movzbl   2(rPC),%eax            # eax<- BB
3743    movzbl   3(rPC),%ecx            # ecx<- CC
3744    GET_VREG(%eax,%eax)             # eax<- vBB
3745    orl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
3746    movzbl   rINST_HI,%ecx         # ecx<- AA
3747    FETCH_INST_WORD(2)
3748    ADVANCE_PC(2)
3749    SET_VREG(%eax,%ecx)
3750    GOTO_NEXT
3751
3752
3753/* ------------------------------ */
3754    .balign 64
3755.L_OP_XOR_INT: /* 0x97 */
3756/* File: x86/OP_XOR_INT.S */
3757/* File: x86/binop.S */
3758    /*
3759     * Generic 32-bit binary operation.  Provide an "instr" line that
3760     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
3761     * This could be an x86 instruction or a function call.  (If the result
3762     * comes back in a register other than eax, you can override "result".)
3763     *
3764     * For: add-int, sub-int, and-int, or-int,
3765     *      xor-int, shl-int, shr-int, ushr-int
3766     */
3767    /* binop vAA, vBB, vCC */
3768    movzbl   2(rPC),%eax            # eax<- BB
3769    movzbl   3(rPC),%ecx            # ecx<- CC
3770    GET_VREG(%eax,%eax)             # eax<- vBB
3771    xorl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
3772    movzbl   rINST_HI,%ecx         # ecx<- AA
3773    FETCH_INST_WORD(2)
3774    ADVANCE_PC(2)
3775    SET_VREG(%eax,%ecx)
3776    GOTO_NEXT
3777
3778
3779/* ------------------------------ */
3780    .balign 64
3781.L_OP_SHL_INT: /* 0x98 */
3782/* File: x86/OP_SHL_INT.S */
3783/* File: x86/binop1.S */
3784    /*
3785     * Generic 32-bit binary operation in which both operands loaded to
3786     * registers (op0 in eax, op1 in ecx).
3787     */
3788    /* binop vAA, vBB, vCC */
3789    movzbl   2(rPC),%eax            # eax<- BB
3790    movzbl   3(rPC),%ecx            # ecx<- CC
3791    GET_VREG(%eax,%eax)             # eax<- vBB
3792    GET_VREG(%ecx,%ecx)             # eax<- vBB
3793    sall    %cl,%eax                          # ex: addl    %ecx,%eax
3794    movzbl   rINST_HI,%ecx          # tmp<- AA
3795    FETCH_INST_WORD(2)
3796    ADVANCE_PC(2)
3797    SET_VREG(%eax,%ecx)
3798    GOTO_NEXT
3799
3800
3801/* ------------------------------ */
3802    .balign 64
3803.L_OP_SHR_INT: /* 0x99 */
3804/* File: x86/OP_SHR_INT.S */
3805/* File: x86/binop1.S */
3806    /*
3807     * Generic 32-bit binary operation in which both operands loaded to
3808     * registers (op0 in eax, op1 in ecx).
3809     */
3810    /* binop vAA, vBB, vCC */
3811    movzbl   2(rPC),%eax            # eax<- BB
3812    movzbl   3(rPC),%ecx            # ecx<- CC
3813    GET_VREG(%eax,%eax)             # eax<- vBB
3814    GET_VREG(%ecx,%ecx)             # eax<- vBB
3815    sarl    %cl,%eax                          # ex: addl    %ecx,%eax
3816    movzbl   rINST_HI,%ecx          # tmp<- AA
3817    FETCH_INST_WORD(2)
3818    ADVANCE_PC(2)
3819    SET_VREG(%eax,%ecx)
3820    GOTO_NEXT
3821
3822
3823/* ------------------------------ */
3824    .balign 64
3825.L_OP_USHR_INT: /* 0x9a */
3826/* File: x86/OP_USHR_INT.S */
3827/* File: x86/binop1.S */
3828    /*
3829     * Generic 32-bit binary operation in which both operands loaded to
3830     * registers (op0 in eax, op1 in ecx).
3831     */
3832    /* binop vAA, vBB, vCC */
3833    movzbl   2(rPC),%eax            # eax<- BB
3834    movzbl   3(rPC),%ecx            # ecx<- CC
3835    GET_VREG(%eax,%eax)             # eax<- vBB
3836    GET_VREG(%ecx,%ecx)             # eax<- vBB
3837    shrl    %cl,%eax                          # ex: addl    %ecx,%eax
3838    movzbl   rINST_HI,%ecx          # tmp<- AA
3839    FETCH_INST_WORD(2)
3840    ADVANCE_PC(2)
3841    SET_VREG(%eax,%ecx)
3842    GOTO_NEXT
3843
3844
3845/* ------------------------------ */
3846    .balign 64
3847.L_OP_ADD_LONG: /* 0x9b */
3848/* File: x86/OP_ADD_LONG.S */
3849/* File: x86/binopWide.S */
3850    /*
3851     * Generic 64-bit binary operation.
3852     */
3853    /* binop vAA, vBB, vCC */
3854
3855    movzbl    2(rPC),%eax               # eax<- BB
3856    movzbl    3(rPC),%ecx               # ecx<- CC
3857    SPILL(rPC)
3858    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
3859    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
3860    addl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
3861    adcl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
3862    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
3863    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
3864    UNSPILL(rPC)
3865    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
3866    FETCH_INST_WORD(2)
3867    ADVANCE_PC(2)
3868    GOTO_NEXT
3869
3870
3871/* ------------------------------ */
3872    .balign 64
3873.L_OP_SUB_LONG: /* 0x9c */
3874/* File: x86/OP_SUB_LONG.S */
3875/* File: x86/binopWide.S */
3876    /*
3877     * Generic 64-bit binary operation.
3878     */
3879    /* binop vAA, vBB, vCC */
3880
3881    movzbl    2(rPC),%eax               # eax<- BB
3882    movzbl    3(rPC),%ecx               # ecx<- CC
3883    SPILL(rPC)
3884    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
3885    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
3886    subl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
3887    sbbl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
3888    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
3889    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
3890    UNSPILL(rPC)
3891    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
3892    FETCH_INST_WORD(2)
3893    ADVANCE_PC(2)
3894    GOTO_NEXT
3895
3896
3897/* ------------------------------ */
3898    .balign 64
3899.L_OP_MUL_LONG: /* 0x9d */
3900/* File: x86/OP_MUL_LONG.S */
3901    /*
3902     * Signed 64-bit integer multiply.
3903     *
3904     * We could definately use more free registers for
3905     * this code.  We must spill rPC (edx) because it
3906     * is used by imul.  We'll also spill rINST (ebx),
3907     * giving us eax, ebc, ecx and edx as computational
3908     * temps.  On top of that, we'll spill rIBASE (edi)
3909     * for use as the vB pointer and rFP (esi) for use
3910     * as the vC pointer.  Yuck.
3911     */
3912    /* mul-long vAA, vBB, vCC */
3913    movzbl    2(rPC),%eax              # eax<- B
3914    movzbl    3(rPC),%ecx              # ecx<- C
3915    SPILL(rPC)
3916    SPILL(rIBASE)
3917    SPILL(rFP)
3918    SPILL(rINST_FULL)
3919    leal      (rFP,%eax,4),rIBASE      # rIBASE<- &v[B]
3920    leal      (rFP,%ecx,4),rFP         # rFP<- &v[C]
3921    movl      4(rIBASE),%ecx      # ecx<- Bmsw
3922    imull     (rFP),%ecx          # ecx<- (Bmsw*Clsw)
3923    movl      4(rFP),%eax         # eax<- Cmsw
3924    imull     (rIBASE),%eax       # eax<- (Cmsw*Blsw)
3925    addl      %eax,%ecx           # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw)
3926    movl      (rFP),%eax          # eax<- Clsw
3927    mull      (rIBASE)            # eax<- (Clsw*Alsw)
3928    UNSPILL(rINST_FULL)
3929    UNSPILL(rFP)
3930    jmp       .LOP_MUL_LONG_continue
3931
3932/* ------------------------------ */
3933    .balign 64
3934.L_OP_DIV_LONG: /* 0x9e */
3935/* File: x86/OP_DIV_LONG.S */
3936    /* div vAA, vBB, vCC */
3937    movzbl    3(rPC),%eax              # eax<- CC
3938    movzbl    2(rPC),%ecx              # ecx<- BB
3939    SPILL(rPC)
3940    GET_VREG_WORD(rPC,%eax,0)
3941    GET_VREG_WORD(%eax,%eax,1)
3942    movl     rPC,OUT_ARG2(%esp)
3943    testl    %eax,%eax
3944    je       .LOP_DIV_LONG_check_zero
3945    cmpl     $-1,%eax
3946    je       .LOP_DIV_LONG_check_neg1
3947.LOP_DIV_LONG_notSpecial:
3948    GET_VREG_WORD(rPC,%ecx,0)
3949    GET_VREG_WORD(%ecx,%ecx,1)
3950.LOP_DIV_LONG_notSpecial1:
3951    movl     %eax,OUT_ARG3(%esp)
3952    movl     rPC,OUT_ARG0(%esp)
3953    movl     %ecx,OUT_ARG1(%esp)
3954    jmp      .LOP_DIV_LONG_continue
3955
3956/* ------------------------------ */
3957    .balign 64
3958.L_OP_REM_LONG: /* 0x9f */
3959/* File: x86/OP_REM_LONG.S */
3960/* File: x86/OP_DIV_LONG.S */
3961    /* div vAA, vBB, vCC */
3962    movzbl    3(rPC),%eax              # eax<- CC
3963    movzbl    2(rPC),%ecx              # ecx<- BB
3964    SPILL(rPC)
3965    GET_VREG_WORD(rPC,%eax,0)
3966    GET_VREG_WORD(%eax,%eax,1)
3967    movl     rPC,OUT_ARG2(%esp)
3968    testl    %eax,%eax
3969    je       .LOP_REM_LONG_check_zero
3970    cmpl     $-1,%eax
3971    je       .LOP_REM_LONG_check_neg1
3972.LOP_REM_LONG_notSpecial:
3973    GET_VREG_WORD(rPC,%ecx,0)
3974    GET_VREG_WORD(%ecx,%ecx,1)
3975.LOP_REM_LONG_notSpecial1:
3976    movl     %eax,OUT_ARG3(%esp)
3977    movl     rPC,OUT_ARG0(%esp)
3978    movl     %ecx,OUT_ARG1(%esp)
3979    jmp      .LOP_REM_LONG_continue
3980
3981
3982/* ------------------------------ */
3983    .balign 64
3984.L_OP_AND_LONG: /* 0xa0 */
3985/* File: x86/OP_AND_LONG.S */
3986/* File: x86/binopWide.S */
3987    /*
3988     * Generic 64-bit binary operation.
3989     */
3990    /* binop vAA, vBB, vCC */
3991
3992    movzbl    2(rPC),%eax               # eax<- BB
3993    movzbl    3(rPC),%ecx               # ecx<- CC
3994    SPILL(rPC)
3995    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
3996    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
3997    andl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
3998    andl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
3999    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
4000    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
4001    UNSPILL(rPC)
4002    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
4003    FETCH_INST_WORD(2)
4004    ADVANCE_PC(2)
4005    GOTO_NEXT
4006
4007
4008/* ------------------------------ */
4009    .balign 64
4010.L_OP_OR_LONG: /* 0xa1 */
4011/* File: x86/OP_OR_LONG.S */
4012/* File: x86/binopWide.S */
4013    /*
4014     * Generic 64-bit binary operation.
4015     */
4016    /* binop vAA, vBB, vCC */
4017
4018    movzbl    2(rPC),%eax               # eax<- BB
4019    movzbl    3(rPC),%ecx               # ecx<- CC
4020    SPILL(rPC)
4021    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
4022    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
4023    orl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
4024    orl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4025    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
4026    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
4027    UNSPILL(rPC)
4028    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
4029    FETCH_INST_WORD(2)
4030    ADVANCE_PC(2)
4031    GOTO_NEXT
4032
4033
4034/* ------------------------------ */
4035    .balign 64
4036.L_OP_XOR_LONG: /* 0xa2 */
4037/* File: x86/OP_XOR_LONG.S */
4038/* File: x86/binopWide.S */
4039    /*
4040     * Generic 64-bit binary operation.
4041     */
4042    /* binop vAA, vBB, vCC */
4043
4044    movzbl    2(rPC),%eax               # eax<- BB
4045    movzbl    3(rPC),%ecx               # ecx<- CC
4046    SPILL(rPC)
4047    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
4048    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
4049    xorl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
4050    xorl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
4051    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
4052    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
4053    UNSPILL(rPC)
4054    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
4055    FETCH_INST_WORD(2)
4056    ADVANCE_PC(2)
4057    GOTO_NEXT
4058
4059
4060/* ------------------------------ */
4061    .balign 64
4062.L_OP_SHL_LONG: /* 0xa3 */
4063/* File: x86/OP_SHL_LONG.S */
4064    /*
4065     * Long integer shift.  This is different from the generic 32/64-bit
4066     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4067     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4068     * 6 bits of the shift distance.  x86 shifts automatically mask off
4069     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4070     * case specially.
4071     */
4072    /* shl-long vAA, vBB, vCC */
4073    /* ecx gets shift count */
4074    /* Need to spill edx */
4075    /* rINST gets AA */
4076    movzbl    2(rPC),%eax               # eax<- BB
4077    movzbl    3(rPC),%ecx               # ecx<- CC
4078    SPILL(rPC)                          # spill edx
4079    GET_VREG_WORD(%edx,%eax,1)          # ecx<- v[BB+1]
4080    GET_VREG  (%ecx,%ecx)               # ecx<- vCC
4081    GET_VREG_WORD(%eax,%eax,0)          # eax<- v[BB+0]
4082    shldl     %eax,%edx
4083    sall      %cl,%eax
4084    testb     $32,%cl
4085    je        2f
4086    movl      %eax,%edx
4087    xorl      %eax,%eax
40882:
4089    movzbl    rINST_HI,%ecx
4090    SET_VREG_WORD(%edx,%ecx,1)         # v[AA+1]<- %edx
4091    UNSPILL(rPC)
4092    FETCH_INST_WORD(2)
4093    jmp       .LOP_SHL_LONG_finish
4094
4095/* ------------------------------ */
4096    .balign 64
4097.L_OP_SHR_LONG: /* 0xa4 */
4098/* File: x86/OP_SHR_LONG.S */
4099    /*
4100     * Long integer shift.  This is different from the generic 32/64-bit
4101     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4102     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4103     * 6 bits of the shift distance.  x86 shifts automatically mask off
4104     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4105     * case specially.
4106     */
4107    /* shr-long vAA, vBB, vCC */
4108    /* ecx gets shift count */
4109    /* Need to spill edx */
4110    /* rINST gets AA */
4111    movzbl    2(rPC),%eax               # eax<- BB
4112    movzbl    3(rPC),%ecx               # ecx<- CC
4113    SPILL(rPC)                          # spill edx
4114    GET_VREG_WORD(%edx,%eax,1)          # edx<- v[BB+1]
4115    GET_VREG  (%ecx,%ecx)               # ecx<- vCC
4116    GET_VREG_WORD(%eax,%eax,0)          # eax<- v[BB+0]
4117    shrdl     %edx,%eax
4118    sarl      %cl,%edx
4119    testb     $32,%cl
4120    je        2f
4121    movl      %edx,%eax
4122    sarl      $31,%edx
41232:
4124    movzbl    rINST_HI,%ecx
4125    SET_VREG_WORD(%edx,%ecx,1)         # v[AA+1]<- edx
4126    UNSPILL(rPC)
4127    FETCH_INST_WORD(2)
4128    jmp       .LOP_SHR_LONG_finish
4129
4130/* ------------------------------ */
4131    .balign 64
4132.L_OP_USHR_LONG: /* 0xa5 */
4133/* File: x86/OP_USHR_LONG.S */
4134    /*
4135     * Long integer shift.  This is different from the generic 32/64-bit
4136     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4137     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4138     * 6 bits of the shift distance.  x86 shifts automatically mask off
4139     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
4140     * case specially.
4141     */
4142    /* shr-long vAA, vBB, vCC */
4143    /* ecx gets shift count */
4144    /* Need to spill edx */
4145    /* rINST gets AA */
4146    movzbl    2(rPC),%eax               # eax<- BB
4147    movzbl    3(rPC),%ecx               # ecx<- CC
4148    SPILL(rPC)                          # spill edx
4149    GET_VREG_WORD(%edx,%eax,1)          # edx<- v[BB+1]
4150    GET_VREG  (%ecx,%ecx)               # ecx<- vCC
4151    GET_VREG_WORD(%eax,%eax,0)          # eax<- v[BB+0]
4152    shrdl     %edx,%eax
4153    shrl      %cl,%edx
4154    testb     $32,%cl
4155    je        2f
4156    movl      %edx,%eax
4157    xorl      %edx,%edx
41582:
4159    movzbl    rINST_HI,%ecx
4160    SET_VREG_WORD(%edx,%ecx,1)         # v[BB+1]<- edx
4161    UNSPILL(rPC)
4162    jmp       .LOP_USHR_LONG_finish
4163
4164/* ------------------------------ */
4165    .balign 64
4166.L_OP_ADD_FLOAT: /* 0xa6 */
4167/* File: x86/OP_ADD_FLOAT.S */
4168/* File: x86/binflop.S */
4169    /*
4170     * Generic 32-bit binary float operation.
4171     *
4172     * For: add-fp, sub-fp, mul-fp, div-fp
4173     */
4174    /* binop vAA, vBB, vCC */
4175    movzbl   2(rPC),%eax            # eax<- CC
4176    movzbl   3(rPC),%ecx            # ecx<- BB
4177    flds    (rFP,%eax,4)           # vCC to fp stack
4178    fadds   (rFP,%ecx,4)           # ex: faddp
4179    movzbl   rINST_HI,%ecx         # ecx<- AA
4180    FETCH_INST_WORD(2)
4181    ADVANCE_PC(2)
4182    fstps   (rFP,%ecx,4)           # %st to vAA
4183    GOTO_NEXT
4184
4185
4186/* ------------------------------ */
4187    .balign 64
4188.L_OP_SUB_FLOAT: /* 0xa7 */
4189/* File: x86/OP_SUB_FLOAT.S */
4190/* File: x86/binflop.S */
4191    /*
4192     * Generic 32-bit binary float operation.
4193     *
4194     * For: add-fp, sub-fp, mul-fp, div-fp
4195     */
4196    /* binop vAA, vBB, vCC */
4197    movzbl   2(rPC),%eax            # eax<- CC
4198    movzbl   3(rPC),%ecx            # ecx<- BB
4199    flds    (rFP,%eax,4)           # vCC to fp stack
4200    fsubs   (rFP,%ecx,4)           # ex: faddp
4201    movzbl   rINST_HI,%ecx         # ecx<- AA
4202    FETCH_INST_WORD(2)
4203    ADVANCE_PC(2)
4204    fstps   (rFP,%ecx,4)           # %st to vAA
4205    GOTO_NEXT
4206
4207
4208/* ------------------------------ */
4209    .balign 64
4210.L_OP_MUL_FLOAT: /* 0xa8 */
4211/* File: x86/OP_MUL_FLOAT.S */
4212/* File: x86/binflop.S */
4213    /*
4214     * Generic 32-bit binary float operation.
4215     *
4216     * For: add-fp, sub-fp, mul-fp, div-fp
4217     */
4218    /* binop vAA, vBB, vCC */
4219    movzbl   2(rPC),%eax            # eax<- CC
4220    movzbl   3(rPC),%ecx            # ecx<- BB
4221    flds    (rFP,%eax,4)           # vCC to fp stack
4222    fmuls   (rFP,%ecx,4)           # ex: faddp
4223    movzbl   rINST_HI,%ecx         # ecx<- AA
4224    FETCH_INST_WORD(2)
4225    ADVANCE_PC(2)
4226    fstps   (rFP,%ecx,4)           # %st to vAA
4227    GOTO_NEXT
4228
4229
4230/* ------------------------------ */
4231    .balign 64
4232.L_OP_DIV_FLOAT: /* 0xa9 */
4233/* File: x86/OP_DIV_FLOAT.S */
4234/* File: x86/binflop.S */
4235    /*
4236     * Generic 32-bit binary float operation.
4237     *
4238     * For: add-fp, sub-fp, mul-fp, div-fp
4239     */
4240    /* binop vAA, vBB, vCC */
4241    movzbl   2(rPC),%eax            # eax<- CC
4242    movzbl   3(rPC),%ecx            # ecx<- BB
4243    flds    (rFP,%eax,4)           # vCC to fp stack
4244    fdivs   (rFP,%ecx,4)           # ex: faddp
4245    movzbl   rINST_HI,%ecx         # ecx<- AA
4246    FETCH_INST_WORD(2)
4247    ADVANCE_PC(2)
4248    fstps   (rFP,%ecx,4)           # %st to vAA
4249    GOTO_NEXT
4250
4251
4252/* ------------------------------ */
4253    .balign 64
4254.L_OP_REM_FLOAT: /* 0xaa */
4255/* File: x86/OP_REM_FLOAT.S */
4256    /* rem_float vAA, vBB, vCC */
4257    movzbl   3(rPC),%ecx            # ecx<- BB
4258    movzbl   2(rPC),%eax            # eax<- CC
4259    flds     (rFP,%ecx,4)           # vCC to fp stack
4260    flds     (rFP,%eax,4)           # vCC to fp stack
4261    movzbl   rINST_HI,%ecx         # ecx<- AA
4262    FETCH_INST_WORD(2)
42631:
4264    fprem
4265    fstsw     %ax
4266    sahf
4267    jp        1b
4268    fstp      %st(1)
4269    ADVANCE_PC(2)
4270    fstps    (rFP,%ecx,4)           # %st to vAA
4271    GOTO_NEXT
4272
4273/* ------------------------------ */
4274    .balign 64
4275.L_OP_ADD_DOUBLE: /* 0xab */
4276/* File: x86/OP_ADD_DOUBLE.S */
4277/* File: x86/binflop.S */
4278    /*
4279     * Generic 32-bit binary float operation.
4280     *
4281     * For: add-fp, sub-fp, mul-fp, div-fp
4282     */
4283    /* binop vAA, vBB, vCC */
4284    movzbl   2(rPC),%eax            # eax<- CC
4285    movzbl   3(rPC),%ecx            # ecx<- BB
4286    fldl    (rFP,%eax,4)           # vCC to fp stack
4287    faddl   (rFP,%ecx,4)           # ex: faddp
4288    movzbl   rINST_HI,%ecx         # ecx<- AA
4289    FETCH_INST_WORD(2)
4290    ADVANCE_PC(2)
4291    fstpl   (rFP,%ecx,4)           # %st to vAA
4292    GOTO_NEXT
4293
4294
4295/* ------------------------------ */
4296    .balign 64
4297.L_OP_SUB_DOUBLE: /* 0xac */
4298/* File: x86/OP_SUB_DOUBLE.S */
4299/* File: x86/binflop.S */
4300    /*
4301     * Generic 32-bit binary float operation.
4302     *
4303     * For: add-fp, sub-fp, mul-fp, div-fp
4304     */
4305    /* binop vAA, vBB, vCC */
4306    movzbl   2(rPC),%eax            # eax<- CC
4307    movzbl   3(rPC),%ecx            # ecx<- BB
4308    fldl    (rFP,%eax,4)           # vCC to fp stack
4309    fsubl   (rFP,%ecx,4)           # ex: faddp
4310    movzbl   rINST_HI,%ecx         # ecx<- AA
4311    FETCH_INST_WORD(2)
4312    ADVANCE_PC(2)
4313    fstpl   (rFP,%ecx,4)           # %st to vAA
4314    GOTO_NEXT
4315
4316
4317/* ------------------------------ */
4318    .balign 64
4319.L_OP_MUL_DOUBLE: /* 0xad */
4320/* File: x86/OP_MUL_DOUBLE.S */
4321/* File: x86/binflop.S */
4322    /*
4323     * Generic 32-bit binary float operation.
4324     *
4325     * For: add-fp, sub-fp, mul-fp, div-fp
4326     */
4327    /* binop vAA, vBB, vCC */
4328    movzbl   2(rPC),%eax            # eax<- CC
4329    movzbl   3(rPC),%ecx            # ecx<- BB
4330    fldl    (rFP,%eax,4)           # vCC to fp stack
4331    fmull   (rFP,%ecx,4)           # ex: faddp
4332    movzbl   rINST_HI,%ecx         # ecx<- AA
4333    FETCH_INST_WORD(2)
4334    ADVANCE_PC(2)
4335    fstpl   (rFP,%ecx,4)           # %st to vAA
4336    GOTO_NEXT
4337
4338
4339/* ------------------------------ */
4340    .balign 64
4341.L_OP_DIV_DOUBLE: /* 0xae */
4342/* File: x86/OP_DIV_DOUBLE.S */
4343/* File: x86/binflop.S */
4344    /*
4345     * Generic 32-bit binary float operation.
4346     *
4347     * For: add-fp, sub-fp, mul-fp, div-fp
4348     */
4349    /* binop vAA, vBB, vCC */
4350    movzbl   2(rPC),%eax            # eax<- CC
4351    movzbl   3(rPC),%ecx            # ecx<- BB
4352    fldl    (rFP,%eax,4)           # vCC to fp stack
4353    fdivl   (rFP,%ecx,4)           # ex: faddp
4354    movzbl   rINST_HI,%ecx         # ecx<- AA
4355    FETCH_INST_WORD(2)
4356    ADVANCE_PC(2)
4357    fstpl   (rFP,%ecx,4)           # %st to vAA
4358    GOTO_NEXT
4359
4360
4361/* ------------------------------ */
4362    .balign 64
4363.L_OP_REM_DOUBLE: /* 0xaf */
4364/* File: x86/OP_REM_DOUBLE.S */
4365    /* rem_float vAA, vBB, vCC */
4366    movzbl   3(rPC),%ecx            # ecx<- BB
4367    movzbl   2(rPC),%eax            # eax<- CC
4368    fldl     (rFP,%ecx,4)           # vCC to fp stack
4369    fldl     (rFP,%eax,4)           # vCC to fp stack
4370    movzbl   rINST_HI,%ecx          # ecx<- AA
4371    FETCH_INST_WORD(2)
43721:
4373    fprem
4374    fstsw     %ax
4375    sahf
4376    jp        1b
4377    fstp      %st(1)
4378    ADVANCE_PC(2)
4379    fstpl    (rFP,%ecx,4)           # %st to vAA
4380    GOTO_NEXT
4381
4382/* ------------------------------ */
4383    .balign 64
4384.L_OP_ADD_INT_2ADDR: /* 0xb0 */
4385/* File: x86/OP_ADD_INT_2ADDR.S */
4386/* File: x86/binop2addr.S */
4387    /*
4388     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4389     * that specifies an instruction that performs "result = r0 op r1".
4390     * This could be an ARM instruction or a function call.  (If the result
4391     * comes back in a register other than r0, you can override "result".)
4392     *
4393     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4394     * vCC (r1).  Useful for integer division and modulus.
4395     *
4396     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4397     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4398     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4399     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4400     */
4401    /* binop/2addr vA, vB */
4402    movzx   rINST_HI,%ecx               # ecx<- A+
4403    sarl    $12,rINST_FULL             # rINST_FULL<- B
4404    GET_VREG(%eax,rINST_FULL)           # eax<- vB
4405    FETCH_INST_WORD(1)
4406    andb    $0xf,%cl                   # ecx<- A
4407    addl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
4408    ADVANCE_PC(1)
4409    GOTO_NEXT
4410
4411
4412/* ------------------------------ */
4413    .balign 64
4414.L_OP_SUB_INT_2ADDR: /* 0xb1 */
4415/* File: x86/OP_SUB_INT_2ADDR.S */
4416/* File: x86/binop2addr.S */
4417    /*
4418     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4419     * that specifies an instruction that performs "result = r0 op r1".
4420     * This could be an ARM instruction or a function call.  (If the result
4421     * comes back in a register other than r0, you can override "result".)
4422     *
4423     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4424     * vCC (r1).  Useful for integer division and modulus.
4425     *
4426     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4427     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4428     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4429     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4430     */
4431    /* binop/2addr vA, vB */
4432    movzx   rINST_HI,%ecx               # ecx<- A+
4433    sarl    $12,rINST_FULL             # rINST_FULL<- B
4434    GET_VREG(%eax,rINST_FULL)           # eax<- vB
4435    FETCH_INST_WORD(1)
4436    andb    $0xf,%cl                   # ecx<- A
4437    subl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
4438    ADVANCE_PC(1)
4439    GOTO_NEXT
4440
4441
4442/* ------------------------------ */
4443    .balign 64
4444.L_OP_MUL_INT_2ADDR: /* 0xb2 */
4445/* File: x86/OP_MUL_INT_2ADDR.S */
4446    /* mul vA, vB */
4447    movzx   rINST_HI,%ecx               # ecx<- A+
4448    sarl    $12,rINST_FULL             # rINST_FULL<- B
4449    GET_VREG(%eax,rINST_FULL)           # eax<- vB
4450    andb    $0xf,%cl                   # ecx<- A
4451    SPILL(rPC)
4452    imull   (rFP,%ecx,4),%eax
4453    UNSPILL(rPC)
4454    SET_VREG(%eax,%ecx)
4455    FETCH_INST_WORD(1)
4456    ADVANCE_PC(1)
4457    GOTO_NEXT
4458
4459/* ------------------------------ */
4460    .balign 64
4461.L_OP_DIV_INT_2ADDR: /* 0xb3 */
4462/* File: x86/OP_DIV_INT_2ADDR.S */
4463/* File: x86/bindiv2addr.S */
4464    /*
4465     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
4466     * op1=-1.
4467     */
4468    /* div/rem/2addr vA, vB */
4469    movzx    rINST_HI,%ecx          # eax<- BA
4470    sarl     $4,%ecx               # ecx<- B
4471    GET_VREG(%ecx,%ecx)             # eax<- vBB
4472    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
4473    andb     $0xf,rINST_LO         # rINST_FULL<- A
4474    GET_VREG(%eax,rINST_FULL)       # eax<- vBB
4475    SPILL(rPC)
4476    cmpl     $0,%ecx
4477    je       common_errDivideByZero
4478    cmpl     $-1,%ecx
4479    jne      .LOP_DIV_INT_2ADDR_continue_div2addr
4480    cmpl     $0x80000000,%eax
4481    jne      .LOP_DIV_INT_2ADDR_continue_div2addr
4482    movl     $0x80000000,%eax
4483    jmp      .LOP_DIV_INT_2ADDR_finish_div2addr
4484
4485
4486
4487/* ------------------------------ */
4488    .balign 64
4489.L_OP_REM_INT_2ADDR: /* 0xb4 */
4490/* File: x86/OP_REM_INT_2ADDR.S */
4491/* File: x86/bindiv2addr.S */
4492    /*
4493     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
4494     * op1=-1.
4495     */
4496    /* div/rem/2addr vA, vB */
4497    movzx    rINST_HI,%ecx          # eax<- BA
4498    sarl     $4,%ecx               # ecx<- B
4499    GET_VREG(%ecx,%ecx)             # eax<- vBB
4500    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
4501    andb     $0xf,rINST_LO         # rINST_FULL<- A
4502    GET_VREG(%eax,rINST_FULL)       # eax<- vBB
4503    SPILL(rPC)
4504    cmpl     $0,%ecx
4505    je       common_errDivideByZero
4506    cmpl     $-1,%ecx
4507    jne      .LOP_REM_INT_2ADDR_continue_div2addr
4508    cmpl     $0x80000000,%eax
4509    jne      .LOP_REM_INT_2ADDR_continue_div2addr
4510    movl     $0,%edx
4511    jmp      .LOP_REM_INT_2ADDR_finish_div2addr
4512
4513
4514
4515/* ------------------------------ */
4516    .balign 64
4517.L_OP_AND_INT_2ADDR: /* 0xb5 */
4518/* File: x86/OP_AND_INT_2ADDR.S */
4519/* File: x86/binop2addr.S */
4520    /*
4521     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4522     * that specifies an instruction that performs "result = r0 op r1".
4523     * This could be an ARM instruction or a function call.  (If the result
4524     * comes back in a register other than r0, you can override "result".)
4525     *
4526     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4527     * vCC (r1).  Useful for integer division and modulus.
4528     *
4529     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4530     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4531     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4532     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4533     */
4534    /* binop/2addr vA, vB */
4535    movzx   rINST_HI,%ecx               # ecx<- A+
4536    sarl    $12,rINST_FULL             # rINST_FULL<- B
4537    GET_VREG(%eax,rINST_FULL)           # eax<- vB
4538    FETCH_INST_WORD(1)
4539    andb    $0xf,%cl                   # ecx<- A
4540    andl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
4541    ADVANCE_PC(1)
4542    GOTO_NEXT
4543
4544
4545/* ------------------------------ */
4546    .balign 64
4547.L_OP_OR_INT_2ADDR: /* 0xb6 */
4548/* File: x86/OP_OR_INT_2ADDR.S */
4549/* File: x86/binop2addr.S */
4550    /*
4551     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4552     * that specifies an instruction that performs "result = r0 op r1".
4553     * This could be an ARM instruction or a function call.  (If the result
4554     * comes back in a register other than r0, you can override "result".)
4555     *
4556     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4557     * vCC (r1).  Useful for integer division and modulus.
4558     *
4559     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4560     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4561     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4562     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4563     */
4564    /* binop/2addr vA, vB */
4565    movzx   rINST_HI,%ecx               # ecx<- A+
4566    sarl    $12,rINST_FULL             # rINST_FULL<- B
4567    GET_VREG(%eax,rINST_FULL)           # eax<- vB
4568    FETCH_INST_WORD(1)
4569    andb    $0xf,%cl                   # ecx<- A
4570    orl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
4571    ADVANCE_PC(1)
4572    GOTO_NEXT
4573
4574
4575/* ------------------------------ */
4576    .balign 64
4577.L_OP_XOR_INT_2ADDR: /* 0xb7 */
4578/* File: x86/OP_XOR_INT_2ADDR.S */
4579/* File: x86/binop2addr.S */
4580    /*
4581     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
4582     * that specifies an instruction that performs "result = r0 op r1".
4583     * This could be an ARM instruction or a function call.  (If the result
4584     * comes back in a register other than r0, you can override "result".)
4585     *
4586     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4587     * vCC (r1).  Useful for integer division and modulus.
4588     *
4589     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
4590     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
4591     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
4592     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
4593     */
4594    /* binop/2addr vA, vB */
4595    movzx   rINST_HI,%ecx               # ecx<- A+
4596    sarl    $12,rINST_FULL             # rINST_FULL<- B
4597    GET_VREG(%eax,rINST_FULL)           # eax<- vB
4598    FETCH_INST_WORD(1)
4599    andb    $0xf,%cl                   # ecx<- A
4600    xorl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
4601    ADVANCE_PC(1)
4602    GOTO_NEXT
4603
4604
4605/* ------------------------------ */
4606    .balign 64
4607.L_OP_SHL_INT_2ADDR: /* 0xb8 */
4608/* File: x86/OP_SHL_INT_2ADDR.S */
4609/* File: x86/shop2addr.S */
4610    /*
4611     * Generic 32-bit "shift/2addr" operation.
4612     */
4613    /* shift/2addr vA, vB */
4614    movzx    rINST_HI,%ecx          # eax<- BA
4615    sarl     $4,%ecx               # ecx<- B
4616    GET_VREG(%ecx,%ecx)             # eax<- vBB
4617    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
4618    andb     $0xf,rINST_LO         # rINST_FULL<- A
4619    GET_VREG(%eax,rINST_FULL)       # eax<- vAA
4620    sall    %cl,%eax                          # ex: sarl %cl,%eax
4621    SET_VREG(%eax,rINST_FULL)
4622    FETCH_INST_WORD(1)
4623    ADVANCE_PC(1)
4624    GOTO_NEXT
4625
4626
4627/* ------------------------------ */
4628    .balign 64
4629.L_OP_SHR_INT_2ADDR: /* 0xb9 */
4630/* File: x86/OP_SHR_INT_2ADDR.S */
4631/* File: x86/shop2addr.S */
4632    /*
4633     * Generic 32-bit "shift/2addr" operation.
4634     */
4635    /* shift/2addr vA, vB */
4636    movzx    rINST_HI,%ecx          # eax<- BA
4637    sarl     $4,%ecx               # ecx<- B
4638    GET_VREG(%ecx,%ecx)             # eax<- vBB
4639    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
4640    andb     $0xf,rINST_LO         # rINST_FULL<- A
4641    GET_VREG(%eax,rINST_FULL)       # eax<- vAA
4642    sarl    %cl,%eax                          # ex: sarl %cl,%eax
4643    SET_VREG(%eax,rINST_FULL)
4644    FETCH_INST_WORD(1)
4645    ADVANCE_PC(1)
4646    GOTO_NEXT
4647
4648
4649/* ------------------------------ */
4650    .balign 64
4651.L_OP_USHR_INT_2ADDR: /* 0xba */
4652/* File: x86/OP_USHR_INT_2ADDR.S */
4653/* File: x86/shop2addr.S */
4654    /*
4655     * Generic 32-bit "shift/2addr" operation.
4656     */
4657    /* shift/2addr vA, vB */
4658    movzx    rINST_HI,%ecx          # eax<- BA
4659    sarl     $4,%ecx               # ecx<- B
4660    GET_VREG(%ecx,%ecx)             # eax<- vBB
4661    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
4662    andb     $0xf,rINST_LO         # rINST_FULL<- A
4663    GET_VREG(%eax,rINST_FULL)       # eax<- vAA
4664    shrl    %cl,%eax                          # ex: sarl %cl,%eax
4665    SET_VREG(%eax,rINST_FULL)
4666    FETCH_INST_WORD(1)
4667    ADVANCE_PC(1)
4668    GOTO_NEXT
4669
4670
4671/* ------------------------------ */
4672    .balign 64
4673.L_OP_ADD_LONG_2ADDR: /* 0xbb */
4674/* File: x86/OP_ADD_LONG_2ADDR.S */
4675/* File: x86/binopWide2addr.S */
4676    /*
4677     * Generic 64-bit binary operation.
4678     */
4679    /* binop/2addr vA, vB */
4680    movzbl    rINST_HI,%ecx             # ecx<- BA
4681    sarl      $4,%ecx                  # ecx<- B
4682    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
4683    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
4684    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
4685    andb      $0xF,rINST_LO            # rINST_FULL<- A
4686    addl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
4687    adcl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
4688    FETCH_INST_WORD(1)
4689    ADVANCE_PC(1)
4690    GOTO_NEXT
4691
4692
4693/* ------------------------------ */
4694    .balign 64
4695.L_OP_SUB_LONG_2ADDR: /* 0xbc */
4696/* File: x86/OP_SUB_LONG_2ADDR.S */
4697/* File: x86/binopWide2addr.S */
4698    /*
4699     * Generic 64-bit binary operation.
4700     */
4701    /* binop/2addr vA, vB */
4702    movzbl    rINST_HI,%ecx             # ecx<- BA
4703    sarl      $4,%ecx                  # ecx<- B
4704    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
4705    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
4706    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
4707    andb      $0xF,rINST_LO            # rINST_FULL<- A
4708    subl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
4709    sbbl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
4710    FETCH_INST_WORD(1)
4711    ADVANCE_PC(1)
4712    GOTO_NEXT
4713
4714
4715/* ------------------------------ */
4716    .balign 64
4717.L_OP_MUL_LONG_2ADDR: /* 0xbd */
4718/* File: x86/OP_MUL_LONG_2ADDR.S */
4719    /*
4720     * Signed 64-bit integer multiply, 2-addr version
4721     *
4722     * We could definately use more free registers for
4723     * this code.  We must spill rPC (edx) because it
4724     * is used by imul.  We'll also spill rINST (ebx),
4725     * giving us eax, ebc, ecx and edx as computational
4726     * temps.  On top of that, we'll spill rIBASE (edi)
4727     * for use as the vA pointer and rFP (esi) for use
4728     * as the vB pointer.  Yuck.
4729     */
4730    /* mul-long/2addr vA, vB */
4731    movzbl    rINST_HI,%eax            # eax<- BA
4732    andb      $0xf,%al                # eax<- A
4733    sarl      $12,rINST_FULL          # rINST_FULL<- B
4734    SPILL(rPC)
4735    SPILL(rIBASE)
4736    SPILL(rFP)
4737    leal      (rFP,%eax,4),rIBASE      # rIBASE<- &v[A]
4738    leal      (rFP,rINST_FULL,4),rFP   # rFP<- &v[B]
4739    movl      4(rIBASE),%ecx      # ecx<- Amsw
4740    imull     (rFP),%ecx          # ecx<- (Amsw*Blsw)
4741    movl      4(rFP),%eax         # eax<- Bmsw
4742    imull     (rIBASE),%eax       # eax<- (Bmsw*Alsw)
4743    addl      %eax,%ecx           # ecx<- (Amsw*Blsw)+(Bmsw*Alsw)
4744    movl      (rFP),%eax          # eax<- Blsw
4745    mull      (rIBASE)            # eax<- (Blsw*Alsw)
4746    jmp       .LOP_MUL_LONG_2ADDR_continue
4747
4748/* ------------------------------ */
4749    .balign 64
4750.L_OP_DIV_LONG_2ADDR: /* 0xbe */
4751/* File: x86/OP_DIV_LONG_2ADDR.S */
4752    /* div/2addr vA, vB */
4753    movzbl    rINST_HI,%eax
4754    shrl      $4,%eax                  # eax<- B
4755    movzbl    rINST_HI,rINST_FULL
4756    andb      $0xf,rINST_LO            # rINST_FULL<- A
4757    SPILL(rPC)
4758    GET_VREG_WORD(rPC,%eax,0)
4759    GET_VREG_WORD(%eax,%eax,1)
4760    movl     rPC,OUT_ARG2(%esp)
4761    testl    %eax,%eax
4762    je       .LOP_DIV_LONG_2ADDR_check_zero
4763    cmpl     $-1,%eax
4764    je       .LOP_DIV_LONG_2ADDR_check_neg1
4765.LOP_DIV_LONG_2ADDR_notSpecial:
4766    GET_VREG_WORD(rPC,rINST_FULL,0)
4767    GET_VREG_WORD(%ecx,rINST_FULL,1)
4768.LOP_DIV_LONG_2ADDR_notSpecial1:
4769    jmp      .LOP_DIV_LONG_2ADDR_continue
4770
4771/* ------------------------------ */
4772    .balign 64
4773.L_OP_REM_LONG_2ADDR: /* 0xbf */
4774/* File: x86/OP_REM_LONG_2ADDR.S */
4775/* File: x86/OP_DIV_LONG_2ADDR.S */
4776    /* div/2addr vA, vB */
4777    movzbl    rINST_HI,%eax
4778    shrl      $4,%eax                  # eax<- B
4779    movzbl    rINST_HI,rINST_FULL
4780    andb      $0xf,rINST_LO            # rINST_FULL<- A
4781    SPILL(rPC)
4782    GET_VREG_WORD(rPC,%eax,0)
4783    GET_VREG_WORD(%eax,%eax,1)
4784    movl     rPC,OUT_ARG2(%esp)
4785    testl    %eax,%eax
4786    je       .LOP_REM_LONG_2ADDR_check_zero
4787    cmpl     $-1,%eax
4788    je       .LOP_REM_LONG_2ADDR_check_neg1
4789.LOP_REM_LONG_2ADDR_notSpecial:
4790    GET_VREG_WORD(rPC,rINST_FULL,0)
4791    GET_VREG_WORD(%ecx,rINST_FULL,1)
4792.LOP_REM_LONG_2ADDR_notSpecial1:
4793    jmp      .LOP_REM_LONG_2ADDR_continue
4794
4795
4796/* ------------------------------ */
4797    .balign 64
4798.L_OP_AND_LONG_2ADDR: /* 0xc0 */
4799/* File: x86/OP_AND_LONG_2ADDR.S */
4800/* File: x86/binopWide2addr.S */
4801    /*
4802     * Generic 64-bit binary operation.
4803     */
4804    /* binop/2addr vA, vB */
4805    movzbl    rINST_HI,%ecx             # ecx<- BA
4806    sarl      $4,%ecx                  # ecx<- B
4807    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
4808    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
4809    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
4810    andb      $0xF,rINST_LO            # rINST_FULL<- A
4811    andl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
4812    andl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
4813    FETCH_INST_WORD(1)
4814    ADVANCE_PC(1)
4815    GOTO_NEXT
4816
4817
4818/* ------------------------------ */
4819    .balign 64
4820.L_OP_OR_LONG_2ADDR: /* 0xc1 */
4821/* File: x86/OP_OR_LONG_2ADDR.S */
4822/* File: x86/binopWide2addr.S */
4823    /*
4824     * Generic 64-bit binary operation.
4825     */
4826    /* binop/2addr vA, vB */
4827    movzbl    rINST_HI,%ecx             # ecx<- BA
4828    sarl      $4,%ecx                  # ecx<- B
4829    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
4830    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
4831    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
4832    andb      $0xF,rINST_LO            # rINST_FULL<- A
4833    orl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
4834    orl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
4835    FETCH_INST_WORD(1)
4836    ADVANCE_PC(1)
4837    GOTO_NEXT
4838
4839
4840/* ------------------------------ */
4841    .balign 64
4842.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
4843/* File: x86/OP_XOR_LONG_2ADDR.S */
4844/* File: x86/binopWide2addr.S */
4845    /*
4846     * Generic 64-bit binary operation.
4847     */
4848    /* binop/2addr vA, vB */
4849    movzbl    rINST_HI,%ecx             # ecx<- BA
4850    sarl      $4,%ecx                  # ecx<- B
4851    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
4852    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
4853    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
4854    andb      $0xF,rINST_LO            # rINST_FULL<- A
4855    xorl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
4856    xorl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
4857    FETCH_INST_WORD(1)
4858    ADVANCE_PC(1)
4859    GOTO_NEXT
4860
4861
4862/* ------------------------------ */
4863    .balign 64
4864.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
4865/* File: x86/OP_SHL_LONG_2ADDR.S */
4866    /*
4867     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
4868     * 32-bit shift distance.
4869     */
4870    /* shl-long/2addr vA, vB */
4871    /* ecx gets shift count */
4872    /* Need to spill edx */
4873    /* rINST gets AA */
4874    movzbl    rINST_HI,%ecx             # ecx<- BA
4875    movzbl    rINST_HI,rINST_FULL       # rINST_HI<- BA
4876    andb      $0xf,rINST_LO            # rINST_FULL<- A
4877    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- v[AA+0]
4878    sarl      $4,%ecx                  # ecx<- B
4879    SPILL(rPC)
4880    GET_VREG_WORD(%edx,rINST_FULL,1)    # edx<- v[AA+1]
4881    GET_VREG(%ecx,%ecx)                 # ecx<- vBB
4882    shldl     %eax,%edx
4883    sall      %cl,%eax
4884    testb     $32,%cl
4885    je        2f
4886    movl      %eax,%edx
4887    xorl      %eax,%eax
48882:
4889    SET_VREG_WORD(%edx,rINST_FULL,1)   # v[AA+1]<- edx
4890    UNSPILL(rPC)
4891    jmp       .LOP_SHL_LONG_2ADDR_finish
4892
4893/* ------------------------------ */
4894    .balign 64
4895.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
4896/* File: x86/OP_SHR_LONG_2ADDR.S */
4897    /*
4898     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
4899     * 32-bit shift distance.
4900     */
4901    /* shl-long/2addr vA, vB */
4902    /* ecx gets shift count */
4903    /* Need to spill edx */
4904    /* rINST gets AA */
4905    movzbl    rINST_HI,%ecx             # ecx<- BA
4906    movzbl    rINST_HI,rINST_FULL       # rINST_HI<- BA
4907    andb      $0xf,rINST_LO            # rINST_FULL<- A
4908    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- v[AA+0]
4909    sarl      $4,%ecx                  # ecx<- B
4910    SPILL(rPC)
4911    GET_VREG_WORD(%edx,rINST_FULL,1)    # edx<- v[AA+1]
4912    GET_VREG(%ecx,%ecx)                 # ecx<- vBB
4913    shrdl     %edx,%eax
4914    sarl      %cl,%edx
4915    testb     $32,%cl
4916    je        2f
4917    movl      %edx,%eax
4918    sarl      $31,%edx
49192:
4920    SET_VREG_WORD(%edx,rINST_FULL,1)   # v[AA+1]<- edx
4921    UNSPILL(rPC)
4922    jmp       .LOP_SHR_LONG_2ADDR_finish
4923
4924/* ------------------------------ */
4925    .balign 64
4926.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
4927/* File: x86/OP_USHR_LONG_2ADDR.S */
4928    /*
4929     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
4930     * 32-bit shift distance.
4931     */
4932    /* shl-long/2addr vA, vB */
4933    /* ecx gets shift count */
4934    /* Need to spill edx */
4935    /* rINST gets AA */
4936    movzbl    rINST_HI,%ecx             # ecx<- BA
4937    movzbl    rINST_HI,rINST_FULL       # rINST_HI<- BA
4938    andb      $0xf,rINST_LO            # rINST_FULL<- A
4939    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- v[AA+0]
4940    sarl      $4,%ecx                  # ecx<- B
4941    SPILL(rPC)
4942    GET_VREG_WORD(%edx,rINST_FULL,1)    # edx<- v[AA+1]
4943    GET_VREG(%ecx,%ecx)                 # ecx<- vBB
4944    shrdl     %edx,%eax
4945    shrl      %cl,%edx
4946    testb     $32,%cl
4947    je        2f
4948    movl      %edx,%eax
4949    xorl      %edx,%edx
49502:
4951    SET_VREG_WORD(%edx,rINST_FULL,1)   # v[AA+1]<- edx
4952    UNSPILL(rPC)
4953    jmp       .LOP_USHR_LONG_2ADDR_finish
4954
4955/* ------------------------------ */
4956    .balign 64
4957.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
4958/* File: x86/OP_ADD_FLOAT_2ADDR.S */
4959/* File: x86/binflop2addr.S */
4960    /*
4961     * Generic 32-bit binary float operation.
4962     *
4963     * For: add-fp, sub-fp, mul-fp, div-fp
4964     */
4965
4966    /* binop/2addr vA, vB */
4967    movzx   rINST_HI,%ecx               # ecx<- A+
4968    andb    $0xf,%cl                   # ecx<- A
4969    flds    (rFP,%ecx,4)               # vAA to fp stack
4970    sarl    $12,rINST_FULL             # rINST_FULL<- B
4971    fadds   (rFP,rINST_FULL,4)           # ex: faddp
4972    FETCH_INST_WORD(1)
4973    ADVANCE_PC(1)
4974    fstps    (rFP,%ecx,4)              # %st to vA
4975    GOTO_NEXT
4976
4977
4978/* ------------------------------ */
4979    .balign 64
4980.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
4981/* File: x86/OP_SUB_FLOAT_2ADDR.S */
4982/* File: x86/binflop2addr.S */
4983    /*
4984     * Generic 32-bit binary float operation.
4985     *
4986     * For: add-fp, sub-fp, mul-fp, div-fp
4987     */
4988
4989    /* binop/2addr vA, vB */
4990    movzx   rINST_HI,%ecx               # ecx<- A+
4991    andb    $0xf,%cl                   # ecx<- A
4992    flds    (rFP,%ecx,4)               # vAA to fp stack
4993    sarl    $12,rINST_FULL             # rINST_FULL<- B
4994    fsubs   (rFP,rINST_FULL,4)           # ex: faddp
4995    FETCH_INST_WORD(1)
4996    ADVANCE_PC(1)
4997    fstps    (rFP,%ecx,4)              # %st to vA
4998    GOTO_NEXT
4999
5000
5001/* ------------------------------ */
5002    .balign 64
5003.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
5004/* File: x86/OP_MUL_FLOAT_2ADDR.S */
5005/* File: x86/binflop2addr.S */
5006    /*
5007     * Generic 32-bit binary float operation.
5008     *
5009     * For: add-fp, sub-fp, mul-fp, div-fp
5010     */
5011
5012    /* binop/2addr vA, vB */
5013    movzx   rINST_HI,%ecx               # ecx<- A+
5014    andb    $0xf,%cl                   # ecx<- A
5015    flds    (rFP,%ecx,4)               # vAA to fp stack
5016    sarl    $12,rINST_FULL             # rINST_FULL<- B
5017    fmuls   (rFP,rINST_FULL,4)           # ex: faddp
5018    FETCH_INST_WORD(1)
5019    ADVANCE_PC(1)
5020    fstps    (rFP,%ecx,4)              # %st to vA
5021    GOTO_NEXT
5022
5023
5024/* ------------------------------ */
5025    .balign 64
5026.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
5027/* File: x86/OP_DIV_FLOAT_2ADDR.S */
5028/* File: x86/binflop2addr.S */
5029    /*
5030     * Generic 32-bit binary float operation.
5031     *
5032     * For: add-fp, sub-fp, mul-fp, div-fp
5033     */
5034
5035    /* binop/2addr vA, vB */
5036    movzx   rINST_HI,%ecx               # ecx<- A+
5037    andb    $0xf,%cl                   # ecx<- A
5038    flds    (rFP,%ecx,4)               # vAA to fp stack
5039    sarl    $12,rINST_FULL             # rINST_FULL<- B
5040    fdivs   (rFP,rINST_FULL,4)           # ex: faddp
5041    FETCH_INST_WORD(1)
5042    ADVANCE_PC(1)
5043    fstps    (rFP,%ecx,4)              # %st to vA
5044    GOTO_NEXT
5045
5046
5047/* ------------------------------ */
5048    .balign 64
5049.L_OP_REM_FLOAT_2ADDR: /* 0xca */
5050/* File: x86/OP_REM_FLOAT_2ADDR.S */
5051    /* rem_float/2addr vA, vB */
5052    movzx   rINST_HI,%ecx               # ecx<- A+
5053    sarl    $12,rINST_FULL             # rINST_FULL<- B
5054    flds     (rFP,rINST_FULL,4)         # vBB to fp stack
5055    andb    $0xf,%cl                   # ecx<- A
5056    flds     (rFP,%ecx,4)               # vAA to fp stack
5057    FETCH_INST_WORD(1)
50581:
5059    fprem
5060    fstsw     %ax
5061    sahf
5062    jp        1b
5063    fstp      %st(1)
5064    ADVANCE_PC(1)
5065    fstps    (rFP,%ecx,4)               # %st to vA
5066    GOTO_NEXT
5067
5068/* ------------------------------ */
5069    .balign 64
5070.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
5071/* File: x86/OP_ADD_DOUBLE_2ADDR.S */
5072/* File: x86/binflop2addr.S */
5073    /*
5074     * Generic 32-bit binary float operation.
5075     *
5076     * For: add-fp, sub-fp, mul-fp, div-fp
5077     */
5078
5079    /* binop/2addr vA, vB */
5080    movzx   rINST_HI,%ecx               # ecx<- A+
5081    andb    $0xf,%cl                   # ecx<- A
5082    fldl    (rFP,%ecx,4)               # vAA to fp stack
5083    sarl    $12,rINST_FULL             # rINST_FULL<- B
5084    faddl   (rFP,rINST_FULL,4)           # ex: faddp
5085    FETCH_INST_WORD(1)
5086    ADVANCE_PC(1)
5087    fstpl    (rFP,%ecx,4)              # %st to vA
5088    GOTO_NEXT
5089
5090
5091/* ------------------------------ */
5092    .balign 64
5093.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
5094/* File: x86/OP_SUB_DOUBLE_2ADDR.S */
5095/* File: x86/binflop2addr.S */
5096    /*
5097     * Generic 32-bit binary float operation.
5098     *
5099     * For: add-fp, sub-fp, mul-fp, div-fp
5100     */
5101
5102    /* binop/2addr vA, vB */
5103    movzx   rINST_HI,%ecx               # ecx<- A+
5104    andb    $0xf,%cl                   # ecx<- A
5105    fldl    (rFP,%ecx,4)               # vAA to fp stack
5106    sarl    $12,rINST_FULL             # rINST_FULL<- B
5107    fsubl   (rFP,rINST_FULL,4)           # ex: faddp
5108    FETCH_INST_WORD(1)
5109    ADVANCE_PC(1)
5110    fstpl    (rFP,%ecx,4)              # %st to vA
5111    GOTO_NEXT
5112
5113
5114/* ------------------------------ */
5115    .balign 64
5116.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
5117/* File: x86/OP_MUL_DOUBLE_2ADDR.S */
5118/* File: x86/binflop2addr.S */
5119    /*
5120     * Generic 32-bit binary float operation.
5121     *
5122     * For: add-fp, sub-fp, mul-fp, div-fp
5123     */
5124
5125    /* binop/2addr vA, vB */
5126    movzx   rINST_HI,%ecx               # ecx<- A+
5127    andb    $0xf,%cl                   # ecx<- A
5128    fldl    (rFP,%ecx,4)               # vAA to fp stack
5129    sarl    $12,rINST_FULL             # rINST_FULL<- B
5130    fmull   (rFP,rINST_FULL,4)           # ex: faddp
5131    FETCH_INST_WORD(1)
5132    ADVANCE_PC(1)
5133    fstpl    (rFP,%ecx,4)              # %st to vA
5134    GOTO_NEXT
5135
5136
5137/* ------------------------------ */
5138    .balign 64
5139.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
5140/* File: x86/OP_DIV_DOUBLE_2ADDR.S */
5141/* File: x86/binflop2addr.S */
5142    /*
5143     * Generic 32-bit binary float operation.
5144     *
5145     * For: add-fp, sub-fp, mul-fp, div-fp
5146     */
5147
5148    /* binop/2addr vA, vB */
5149    movzx   rINST_HI,%ecx               # ecx<- A+
5150    andb    $0xf,%cl                   # ecx<- A
5151    fldl    (rFP,%ecx,4)               # vAA to fp stack
5152    sarl    $12,rINST_FULL             # rINST_FULL<- B
5153    fdivl   (rFP,rINST_FULL,4)           # ex: faddp
5154    FETCH_INST_WORD(1)
5155    ADVANCE_PC(1)
5156    fstpl    (rFP,%ecx,4)              # %st to vA
5157    GOTO_NEXT
5158
5159
5160/* ------------------------------ */
5161    .balign 64
5162.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
5163/* File: x86/OP_REM_DOUBLE_2ADDR.S */
5164    /* rem_float/2addr vA, vB */
5165    movzx   rINST_HI,%ecx               # ecx<- A+
5166    sarl    $12,rINST_FULL             # rINST_FULL<- B
5167    fldl     (rFP,rINST_FULL,4)         # vBB to fp stack
5168    andb    $0xf,%cl                   # ecx<- A
5169    fldl     (rFP,%ecx,4)               # vAA to fp stack
5170    FETCH_INST_WORD(1)
51711:
5172    fprem
5173    fstsw     %ax
5174    sahf
5175    jp        1b
5176    fstp      %st(1)
5177    ADVANCE_PC(1)
5178    fstpl    (rFP,%ecx,4)               # %st to vA
5179    GOTO_NEXT
5180
5181/* ------------------------------ */
5182    .balign 64
5183.L_OP_ADD_INT_LIT16: /* 0xd0 */
5184/* File: x86/OP_ADD_INT_LIT16.S */
5185/* File: x86/binopLit16.S */
5186    /*
5187     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5188     * that specifies an instruction that performs "result = eax op ecx".
5189     * This could be an x86 instruction or a function call.  (If the result
5190     * comes back in a register other than eax, you can override "result".)
5191     *
5192     * For: add-int/lit16, rsub-int,
5193     *      and-int/lit16, or-int/lit16, xor-int/lit16
5194     */
5195    /* binop/lit16 vA, vB, #+CCCC */
5196    movzbl   rINST_HI,%eax              # eax<- 000000BA
5197    sarl     $4,%eax                   # eax<- B
5198    GET_VREG(%eax,%eax)                 # eax<- vB
5199    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5200    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5201    andb     $0xf,rINST_LO             # rINST_FULL<- A
5202    addl %ecx,%eax                              # for example: addl %ecx, %eax
5203    SET_VREG(%eax,rINST_FULL)
5204    FETCH_INST_WORD(2)
5205    ADVANCE_PC(2)
5206    GOTO_NEXT
5207
5208
5209/* ------------------------------ */
5210    .balign 64
5211.L_OP_RSUB_INT: /* 0xd1 */
5212/* File: x86/OP_RSUB_INT.S */
5213/* File: x86/binopLit16.S */
5214    /*
5215     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5216     * that specifies an instruction that performs "result = eax op ecx".
5217     * This could be an x86 instruction or a function call.  (If the result
5218     * comes back in a register other than eax, you can override "result".)
5219     *
5220     * For: add-int/lit16, rsub-int,
5221     *      and-int/lit16, or-int/lit16, xor-int/lit16
5222     */
5223    /* binop/lit16 vA, vB, #+CCCC */
5224    movzbl   rINST_HI,%eax              # eax<- 000000BA
5225    sarl     $4,%eax                   # eax<- B
5226    GET_VREG(%eax,%eax)                 # eax<- vB
5227    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5228    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5229    andb     $0xf,rINST_LO             # rINST_FULL<- A
5230    subl %eax,%ecx                              # for example: addl %ecx, %eax
5231    SET_VREG(%ecx,rINST_FULL)
5232    FETCH_INST_WORD(2)
5233    ADVANCE_PC(2)
5234    GOTO_NEXT
5235
5236
5237/* ------------------------------ */
5238    .balign 64
5239.L_OP_MUL_INT_LIT16: /* 0xd2 */
5240/* File: x86/OP_MUL_INT_LIT16.S */
5241    /* mul/lit16 vA, vB, #+CCCC */
5242    /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
5243    movzbl   rINST_HI,%eax              # eax<- 000000BA
5244    sarl     $4,%eax                   # eax<- B
5245    GET_VREG(%eax,%eax)                 # eax<- vB
5246    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5247    SPILL(rPC)
5248    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5249    andb     $0xf,rINST_LO             # rINST_FULL<- A
5250    imull     %ecx,%eax                 # trashes rPC
5251    UNSPILL(rPC)
5252    SET_VREG(%eax,rINST_FULL)
5253    FETCH_INST_WORD(2)
5254    ADVANCE_PC(2)
5255    GOTO_NEXT
5256
5257/* ------------------------------ */
5258    .balign 64
5259.L_OP_DIV_INT_LIT16: /* 0xd3 */
5260/* File: x86/OP_DIV_INT_LIT16.S */
5261/* File: x86/bindivLit16.S */
5262    /*
5263     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
5264     * op1=-1.
5265     */
5266    /* div/rem/lit16 vA, vB, #+CCCC */
5267    /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
5268    movzbl   rINST_HI,%eax              # eax<- 000000BA
5269    sarl     $4,%eax                   # eax<- B
5270    GET_VREG(%eax,%eax)                 # eax<- vB
5271    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5272    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5273    andb     $0xf,rINST_LO             # rINST_FULL<- A
5274    SPILL(rPC)
5275    cmpl     $0,%ecx
5276    je       common_errDivideByZero
5277    cmpl     $-1,%ecx
5278    jne      .LOP_DIV_INT_LIT16_continue_div
5279    cmpl     $0x80000000,%eax
5280    jne      .LOP_DIV_INT_LIT16_continue_div
5281    movl     $0x80000000,%eax
5282    jmp      .LOP_DIV_INT_LIT16_finish_div
5283
5284
5285
5286/* ------------------------------ */
5287    .balign 64
5288.L_OP_REM_INT_LIT16: /* 0xd4 */
5289/* File: x86/OP_REM_INT_LIT16.S */
5290/* File: x86/bindivLit16.S */
5291    /*
5292     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
5293     * op1=-1.
5294     */
5295    /* div/rem/lit16 vA, vB, #+CCCC */
5296    /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
5297    movzbl   rINST_HI,%eax              # eax<- 000000BA
5298    sarl     $4,%eax                   # eax<- B
5299    GET_VREG(%eax,%eax)                 # eax<- vB
5300    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5301    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5302    andb     $0xf,rINST_LO             # rINST_FULL<- A
5303    SPILL(rPC)
5304    cmpl     $0,%ecx
5305    je       common_errDivideByZero
5306    cmpl     $-1,%ecx
5307    jne      .LOP_REM_INT_LIT16_continue_div
5308    cmpl     $0x80000000,%eax
5309    jne      .LOP_REM_INT_LIT16_continue_div
5310    movl     $0,%edx
5311    jmp      .LOP_REM_INT_LIT16_finish_div
5312
5313
5314
5315/* ------------------------------ */
5316    .balign 64
5317.L_OP_AND_INT_LIT16: /* 0xd5 */
5318/* File: x86/OP_AND_INT_LIT16.S */
5319/* File: x86/binopLit16.S */
5320    /*
5321     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5322     * that specifies an instruction that performs "result = eax op ecx".
5323     * This could be an x86 instruction or a function call.  (If the result
5324     * comes back in a register other than eax, you can override "result".)
5325     *
5326     * For: add-int/lit16, rsub-int,
5327     *      and-int/lit16, or-int/lit16, xor-int/lit16
5328     */
5329    /* binop/lit16 vA, vB, #+CCCC */
5330    movzbl   rINST_HI,%eax              # eax<- 000000BA
5331    sarl     $4,%eax                   # eax<- B
5332    GET_VREG(%eax,%eax)                 # eax<- vB
5333    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5334    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5335    andb     $0xf,rINST_LO             # rINST_FULL<- A
5336    andl %ecx,%eax                              # for example: addl %ecx, %eax
5337    SET_VREG(%eax,rINST_FULL)
5338    FETCH_INST_WORD(2)
5339    ADVANCE_PC(2)
5340    GOTO_NEXT
5341
5342
5343/* ------------------------------ */
5344    .balign 64
5345.L_OP_OR_INT_LIT16: /* 0xd6 */
5346/* File: x86/OP_OR_INT_LIT16.S */
5347/* File: x86/binopLit16.S */
5348    /*
5349     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5350     * that specifies an instruction that performs "result = eax op ecx".
5351     * This could be an x86 instruction or a function call.  (If the result
5352     * comes back in a register other than eax, you can override "result".)
5353     *
5354     * For: add-int/lit16, rsub-int,
5355     *      and-int/lit16, or-int/lit16, xor-int/lit16
5356     */
5357    /* binop/lit16 vA, vB, #+CCCC */
5358    movzbl   rINST_HI,%eax              # eax<- 000000BA
5359    sarl     $4,%eax                   # eax<- B
5360    GET_VREG(%eax,%eax)                 # eax<- vB
5361    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5362    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5363    andb     $0xf,rINST_LO             # rINST_FULL<- A
5364    orl     %ecx,%eax                              # for example: addl %ecx, %eax
5365    SET_VREG(%eax,rINST_FULL)
5366    FETCH_INST_WORD(2)
5367    ADVANCE_PC(2)
5368    GOTO_NEXT
5369
5370
5371/* ------------------------------ */
5372    .balign 64
5373.L_OP_XOR_INT_LIT16: /* 0xd7 */
5374/* File: x86/OP_XOR_INT_LIT16.S */
5375/* File: x86/binopLit16.S */
5376    /*
5377     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
5378     * that specifies an instruction that performs "result = eax op ecx".
5379     * This could be an x86 instruction or a function call.  (If the result
5380     * comes back in a register other than eax, you can override "result".)
5381     *
5382     * For: add-int/lit16, rsub-int,
5383     *      and-int/lit16, or-int/lit16, xor-int/lit16
5384     */
5385    /* binop/lit16 vA, vB, #+CCCC */
5386    movzbl   rINST_HI,%eax              # eax<- 000000BA
5387    sarl     $4,%eax                   # eax<- B
5388    GET_VREG(%eax,%eax)                 # eax<- vB
5389    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
5390    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
5391    andb     $0xf,rINST_LO             # rINST_FULL<- A
5392    xor    %ecx,%eax                              # for example: addl %ecx, %eax
5393    SET_VREG(%eax,rINST_FULL)
5394    FETCH_INST_WORD(2)
5395    ADVANCE_PC(2)
5396    GOTO_NEXT
5397
5398
5399/* ------------------------------ */
5400    .balign 64
5401.L_OP_ADD_INT_LIT8: /* 0xd8 */
5402/* File: x86/OP_ADD_INT_LIT8.S */
5403/* File: x86/binopLit8.S */
5404    /*
5405     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5406     * that specifies an instruction that performs "result = eax op ecx".
5407     * This could be an x86 instruction or a function call.  (If the result
5408     * comes back in a register other than r0, you can override "result".)
5409     *
5410     * For: add-int/lit8, rsub-int/lit8
5411     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5412     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5413     */
5414    /* binop/lit8 vAA, vBB, #+CC */
5415    movzbl    2(rPC),%eax              # eax<- BB
5416    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5417    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5418    GET_VREG  (%eax,%eax)              # eax<- rBB
5419    addl %ecx,%eax                             # ex: addl %ecx,%eax
5420    SET_VREG  (%eax,rINST_FULL)
5421    FETCH_INST_WORD(2)
5422    ADVANCE_PC(2)
5423    GOTO_NEXT
5424
5425
5426/* ------------------------------ */
5427    .balign 64
5428.L_OP_RSUB_INT_LIT8: /* 0xd9 */
5429/* File: x86/OP_RSUB_INT_LIT8.S */
5430/* File: x86/binopLit8.S */
5431    /*
5432     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5433     * that specifies an instruction that performs "result = eax op ecx".
5434     * This could be an x86 instruction or a function call.  (If the result
5435     * comes back in a register other than r0, you can override "result".)
5436     *
5437     * For: add-int/lit8, rsub-int/lit8
5438     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5439     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5440     */
5441    /* binop/lit8 vAA, vBB, #+CC */
5442    movzbl    2(rPC),%eax              # eax<- BB
5443    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5444    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5445    GET_VREG  (%eax,%eax)              # eax<- rBB
5446    subl  %eax,%ecx                             # ex: addl %ecx,%eax
5447    SET_VREG  (%ecx,rINST_FULL)
5448    FETCH_INST_WORD(2)
5449    ADVANCE_PC(2)
5450    GOTO_NEXT
5451
5452
5453/* ------------------------------ */
5454    .balign 64
5455.L_OP_MUL_INT_LIT8: /* 0xda */
5456/* File: x86/OP_MUL_INT_LIT8.S */
5457    /* mul/lit8 vAA, vBB, #+CC */
5458    movzbl    2(rPC),%eax              # eax<- BB
5459    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5460    SPILL(rPC)
5461    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5462    GET_VREG  (%eax,%eax)              # eax<- rBB
5463    imull     %ecx,%eax                # trashes rPC
5464    UNSPILL(rPC)
5465    SET_VREG  (%eax,rINST_FULL)
5466    FETCH_INST_WORD(2)
5467    ADVANCE_PC(2)
5468    GOTO_NEXT
5469
5470/* ------------------------------ */
5471    .balign 64
5472.L_OP_DIV_INT_LIT8: /* 0xdb */
5473/* File: x86/OP_DIV_INT_LIT8.S */
5474/* File: x86/bindivLit8.S */
5475    /*
5476     * 32-bit div/rem "lit8" binary operation.  Handles special case of
5477     * op0=minint & op1=-1
5478     */
5479    /* div/rem/lit8 vAA, vBB, #+CC */
5480    movzbl    2(rPC),%eax              # eax<- BB
5481    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5482    GET_VREG  (%eax,%eax)              # eax<- rBB
5483    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5484    SPILL(rPC)
5485    cmpl     $0,%ecx
5486    je       common_errDivideByZero
5487    cmpl     $0x80000000,%eax
5488    jne      .LOP_DIV_INT_LIT8_continue_div
5489    cmpl     $-1,%ecx
5490    jne      .LOP_DIV_INT_LIT8_continue_div
5491    movl     $0x80000000,%eax
5492    jmp      .LOP_DIV_INT_LIT8_finish_div
5493
5494
5495
5496/* ------------------------------ */
5497    .balign 64
5498.L_OP_REM_INT_LIT8: /* 0xdc */
5499/* File: x86/OP_REM_INT_LIT8.S */
5500/* File: x86/bindivLit8.S */
5501    /*
5502     * 32-bit div/rem "lit8" binary operation.  Handles special case of
5503     * op0=minint & op1=-1
5504     */
5505    /* div/rem/lit8 vAA, vBB, #+CC */
5506    movzbl    2(rPC),%eax              # eax<- BB
5507    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5508    GET_VREG  (%eax,%eax)              # eax<- rBB
5509    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5510    SPILL(rPC)
5511    cmpl     $0,%ecx
5512    je       common_errDivideByZero
5513    cmpl     $0x80000000,%eax
5514    jne      .LOP_REM_INT_LIT8_continue_div
5515    cmpl     $-1,%ecx
5516    jne      .LOP_REM_INT_LIT8_continue_div
5517    movl     $0,%edx
5518    jmp      .LOP_REM_INT_LIT8_finish_div
5519
5520
5521
5522/* ------------------------------ */
5523    .balign 64
5524.L_OP_AND_INT_LIT8: /* 0xdd */
5525/* File: x86/OP_AND_INT_LIT8.S */
5526/* File: x86/binopLit8.S */
5527    /*
5528     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5529     * that specifies an instruction that performs "result = eax op ecx".
5530     * This could be an x86 instruction or a function call.  (If the result
5531     * comes back in a register other than r0, you can override "result".)
5532     *
5533     * For: add-int/lit8, rsub-int/lit8
5534     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5535     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5536     */
5537    /* binop/lit8 vAA, vBB, #+CC */
5538    movzbl    2(rPC),%eax              # eax<- BB
5539    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5540    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5541    GET_VREG  (%eax,%eax)              # eax<- rBB
5542    andl %ecx,%eax                             # ex: addl %ecx,%eax
5543    SET_VREG  (%eax,rINST_FULL)
5544    FETCH_INST_WORD(2)
5545    ADVANCE_PC(2)
5546    GOTO_NEXT
5547
5548
5549/* ------------------------------ */
5550    .balign 64
5551.L_OP_OR_INT_LIT8: /* 0xde */
5552/* File: x86/OP_OR_INT_LIT8.S */
5553/* File: x86/binopLit8.S */
5554    /*
5555     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5556     * that specifies an instruction that performs "result = eax op ecx".
5557     * This could be an x86 instruction or a function call.  (If the result
5558     * comes back in a register other than r0, you can override "result".)
5559     *
5560     * For: add-int/lit8, rsub-int/lit8
5561     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5562     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5563     */
5564    /* binop/lit8 vAA, vBB, #+CC */
5565    movzbl    2(rPC),%eax              # eax<- BB
5566    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5567    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5568    GET_VREG  (%eax,%eax)              # eax<- rBB
5569    orl     %ecx,%eax                             # ex: addl %ecx,%eax
5570    SET_VREG  (%eax,rINST_FULL)
5571    FETCH_INST_WORD(2)
5572    ADVANCE_PC(2)
5573    GOTO_NEXT
5574
5575
5576/* ------------------------------ */
5577    .balign 64
5578.L_OP_XOR_INT_LIT8: /* 0xdf */
5579/* File: x86/OP_XOR_INT_LIT8.S */
5580/* File: x86/binopLit8.S */
5581    /*
5582     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5583     * that specifies an instruction that performs "result = eax op ecx".
5584     * This could be an x86 instruction or a function call.  (If the result
5585     * comes back in a register other than r0, you can override "result".)
5586     *
5587     * For: add-int/lit8, rsub-int/lit8
5588     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5589     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5590     */
5591    /* binop/lit8 vAA, vBB, #+CC */
5592    movzbl    2(rPC),%eax              # eax<- BB
5593    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5594    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5595    GET_VREG  (%eax,%eax)              # eax<- rBB
5596    xor    %ecx,%eax                             # ex: addl %ecx,%eax
5597    SET_VREG  (%eax,rINST_FULL)
5598    FETCH_INST_WORD(2)
5599    ADVANCE_PC(2)
5600    GOTO_NEXT
5601
5602
5603/* ------------------------------ */
5604    .balign 64
5605.L_OP_SHL_INT_LIT8: /* 0xe0 */
5606/* File: x86/OP_SHL_INT_LIT8.S */
5607/* File: x86/binopLit8.S */
5608    /*
5609     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5610     * that specifies an instruction that performs "result = eax op ecx".
5611     * This could be an x86 instruction or a function call.  (If the result
5612     * comes back in a register other than r0, you can override "result".)
5613     *
5614     * For: add-int/lit8, rsub-int/lit8
5615     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5616     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5617     */
5618    /* binop/lit8 vAA, vBB, #+CC */
5619    movzbl    2(rPC),%eax              # eax<- BB
5620    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5621    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5622    GET_VREG  (%eax,%eax)              # eax<- rBB
5623    sall  %cl,%eax                             # ex: addl %ecx,%eax
5624    SET_VREG  (%eax,rINST_FULL)
5625    FETCH_INST_WORD(2)
5626    ADVANCE_PC(2)
5627    GOTO_NEXT
5628
5629
5630/* ------------------------------ */
5631    .balign 64
5632.L_OP_SHR_INT_LIT8: /* 0xe1 */
5633/* File: x86/OP_SHR_INT_LIT8.S */
5634/* File: x86/binopLit8.S */
5635    /*
5636     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5637     * that specifies an instruction that performs "result = eax op ecx".
5638     * This could be an x86 instruction or a function call.  (If the result
5639     * comes back in a register other than r0, you can override "result".)
5640     *
5641     * For: add-int/lit8, rsub-int/lit8
5642     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5643     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5644     */
5645    /* binop/lit8 vAA, vBB, #+CC */
5646    movzbl    2(rPC),%eax              # eax<- BB
5647    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5648    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5649    GET_VREG  (%eax,%eax)              # eax<- rBB
5650    sarl    %cl,%eax                             # ex: addl %ecx,%eax
5651    SET_VREG  (%eax,rINST_FULL)
5652    FETCH_INST_WORD(2)
5653    ADVANCE_PC(2)
5654    GOTO_NEXT
5655
5656
5657/* ------------------------------ */
5658    .balign 64
5659.L_OP_USHR_INT_LIT8: /* 0xe2 */
5660/* File: x86/OP_USHR_INT_LIT8.S */
5661/* File: x86/binopLit8.S */
5662    /*
5663     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
5664     * that specifies an instruction that performs "result = eax op ecx".
5665     * This could be an x86 instruction or a function call.  (If the result
5666     * comes back in a register other than r0, you can override "result".)
5667     *
5668     * For: add-int/lit8, rsub-int/lit8
5669     *      and-int/lit8, or-int/lit8, xor-int/lit8,
5670     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
5671     */
5672    /* binop/lit8 vAA, vBB, #+CC */
5673    movzbl    2(rPC),%eax              # eax<- BB
5674    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
5675    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
5676    GET_VREG  (%eax,%eax)              # eax<- rBB
5677    shrl     %cl,%eax                             # ex: addl %ecx,%eax
5678    SET_VREG  (%eax,rINST_FULL)
5679    FETCH_INST_WORD(2)
5680    ADVANCE_PC(2)
5681    GOTO_NEXT
5682
5683
5684/* ------------------------------ */
5685    .balign 64
5686.L_OP_IGET_VOLATILE: /* 0xe3 */
5687    /* (stub) */
5688    GET_GLUE(%ecx)
5689    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5690    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5691    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5692    call      dvmMterp_OP_IGET_VOLATILE     # do the real work
5693    GET_GLUE(%ecx)
5694    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5695    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5696    FETCH_INST()
5697    GOTO_NEXT
5698/* ------------------------------ */
5699    .balign 64
5700.L_OP_IPUT_VOLATILE: /* 0xe4 */
5701    /* (stub) */
5702    GET_GLUE(%ecx)
5703    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5704    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5705    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5706    call      dvmMterp_OP_IPUT_VOLATILE     # do the real work
5707    GET_GLUE(%ecx)
5708    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5709    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5710    FETCH_INST()
5711    GOTO_NEXT
5712/* ------------------------------ */
5713    .balign 64
5714.L_OP_SGET_VOLATILE: /* 0xe5 */
5715    /* (stub) */
5716    GET_GLUE(%ecx)
5717    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5718    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5719    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5720    call      dvmMterp_OP_SGET_VOLATILE     # do the real work
5721    GET_GLUE(%ecx)
5722    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5723    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5724    FETCH_INST()
5725    GOTO_NEXT
5726/* ------------------------------ */
5727    .balign 64
5728.L_OP_SPUT_VOLATILE: /* 0xe6 */
5729    /* (stub) */
5730    GET_GLUE(%ecx)
5731    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5732    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5733    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5734    call      dvmMterp_OP_SPUT_VOLATILE     # do the real work
5735    GET_GLUE(%ecx)
5736    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5737    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5738    FETCH_INST()
5739    GOTO_NEXT
5740/* ------------------------------ */
5741    .balign 64
5742.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
5743    /* (stub) */
5744    GET_GLUE(%ecx)
5745    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5746    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5747    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5748    call      dvmMterp_OP_IGET_OBJECT_VOLATILE     # do the real work
5749    GET_GLUE(%ecx)
5750    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5751    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5752    FETCH_INST()
5753    GOTO_NEXT
5754/* ------------------------------ */
5755    .balign 64
5756.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
5757    /* (stub) */
5758    GET_GLUE(%ecx)
5759    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5760    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5761    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5762    call      dvmMterp_OP_IGET_WIDE_VOLATILE     # do the real work
5763    GET_GLUE(%ecx)
5764    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5765    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5766    FETCH_INST()
5767    GOTO_NEXT
5768/* ------------------------------ */
5769    .balign 64
5770.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
5771    /* (stub) */
5772    GET_GLUE(%ecx)
5773    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5774    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5775    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5776    call      dvmMterp_OP_IPUT_WIDE_VOLATILE     # do the real work
5777    GET_GLUE(%ecx)
5778    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5779    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5780    FETCH_INST()
5781    GOTO_NEXT
5782/* ------------------------------ */
5783    .balign 64
5784.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
5785    /* (stub) */
5786    GET_GLUE(%ecx)
5787    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5788    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5789    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5790    call      dvmMterp_OP_SGET_WIDE_VOLATILE     # do the real work
5791    GET_GLUE(%ecx)
5792    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5793    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5794    FETCH_INST()
5795    GOTO_NEXT
5796/* ------------------------------ */
5797    .balign 64
5798.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
5799    /* (stub) */
5800    GET_GLUE(%ecx)
5801    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5802    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5803    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5804    call      dvmMterp_OP_SPUT_WIDE_VOLATILE     # do the real work
5805    GET_GLUE(%ecx)
5806    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5807    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5808    FETCH_INST()
5809    GOTO_NEXT
5810/* ------------------------------ */
5811    .balign 64
5812.L_OP_BREAKPOINT: /* 0xec */
5813/* File: x86/OP_BREAKPOINT.S */
5814/* File: x86/unused.S */
5815    jmp     common_abort
5816
5817
5818/* ------------------------------ */
5819    .balign 64
5820.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
5821/* File: x86/OP_THROW_VERIFICATION_ERROR.S */
5822    /*
5823     * Handle a throw-verification-error instruction.  This throws an
5824     * exception for an error discovered during verification.  The
5825     * exception is indicated by AA, with some detail provided by BBBB.
5826     */
5827    /* op AA, ref@BBBB */
5828    GET_GLUE(%ecx)
5829    movzwl   2(rPC),%eax                     # eax<- BBBB
5830    movl     offGlue_method(%ecx),%ecx       # ecx<- glue->method
5831    EXPORT_PC()
5832    movzbl   rINST_HI,rINST_FULL             # rINST_FULL<- AA
5833    movl     %eax,OUT_ARG2(%esp)             # arg2<- BBBB
5834    movl     rINST_FULL,OUT_ARG1(%esp)       # arg1<- AA
5835    movl     %ecx,OUT_ARG0(%esp)             # arg0<- method
5836    SPILL(rPC)
5837    call     dvmThrowVerificationError       # call(method, kind, ref)
5838    UNSPILL(rPC)
5839    jmp      common_exceptionThrown          # handle exception
5840
5841/* ------------------------------ */
5842    .balign 64
5843.L_OP_EXECUTE_INLINE: /* 0xee */
5844/* File: x86/OP_EXECUTE_INLINE.S */
5845    /*
5846     * Execute a "native inline" instruction.
5847     *
5848     * We will be calling through a function table:
5849     *
5850     * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
5851     *
5852     */
5853    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
5854    GET_GLUE(%ecx)
5855    EXPORT_PC()
5856    movzwl    2(rPC),%eax               # eax<- BBBB
5857    leal      offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
5858    movl      %ecx,OUT_ARG4(%esp)
5859    sarl      $12,rINST_FULL           # rINST_FULL<- arg count (0-4)
5860    SPILL(rPC)
5861    call      .LOP_EXECUTE_INLINE_continue      # make call; will return after
5862    UNSPILL(rPC)
5863    testl     %eax,%eax                 # successful?
5864    FETCH_INST_WORD(3)
5865    je        common_exceptionThrown    # no, handle exception
5866    ADVANCE_PC(3)
5867    GOTO_NEXT
5868
5869/* ------------------------------ */
5870    .balign 64
5871.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
5872    /* (stub) */
5873    GET_GLUE(%ecx)
5874    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
5875    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
5876    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
5877    call      dvmMterp_OP_EXECUTE_INLINE_RANGE     # do the real work
5878    GET_GLUE(%ecx)
5879    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
5880    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
5881    FETCH_INST()
5882    GOTO_NEXT
5883/* ------------------------------ */
5884    .balign 64
5885.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
5886/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */
5887    /*
5888     * invoke-direct-empty is a no-op in a "standard" interpreter.
5889     */
5890    FETCH_INST_WORD(3)
5891    ADVANCE_PC(3)
5892    GOTO_NEXT
5893
5894/* ------------------------------ */
5895    .balign 64
5896.L_OP_UNUSED_F1: /* 0xf1 */
5897/* File: x86/OP_UNUSED_F1.S */
5898/* File: x86/unused.S */
5899    jmp     common_abort
5900
5901
5902/* ------------------------------ */
5903    .balign 64
5904.L_OP_IGET_QUICK: /* 0xf2 */
5905/* File: x86/OP_IGET_QUICK.S */
5906    /* For: iget-quick, iget-object-quick */
5907    /* op vA, vB, offset@CCCC */
5908    movzbl    rINST_HI,%ecx             # ecx<- BA
5909    sarl      $4,%ecx                  # ecx<- B
5910    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5911    movzwl    2(rPC),%eax               # eax<- field byte offset
5912    cmpl      $0,%ecx                  # is object null?
5913    je        common_errNullObject
5914    movl      (%ecx,%eax,1),%eax
5915    movzbl    rINST_HI,%ecx
5916    FETCH_INST_WORD(2)
5917    ADVANCE_PC(2)
5918    andb      $0xf,%cl                 # rINST_FULL<- A
5919    SET_VREG  (%eax,%ecx)               # fp[A]<- result
5920    GOTO_NEXT
5921
5922/* ------------------------------ */
5923    .balign 64
5924.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
5925/* File: x86/OP_IGET_WIDE_QUICK.S */
5926    /* For: iget-wide-quick */
5927    /* op vA, vB, offset@CCCC */
5928    movzbl    rINST_HI,%ecx             # ecx<- BA
5929    sarl      $4,%ecx                  # ecx<- B
5930    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5931    movzwl    2(rPC),%eax               # eax<- field byte offset
5932    cmpl      $0,%ecx                  # is object null?
5933    je        common_errNullObject
5934    leal      (%ecx,%eax,1),%eax        # eax<- address of 64-bit source
5935    movl      (%eax),%ecx               # ecx<- lsw
5936    movl      4(%eax),%eax               # eax<- msw
5937    movzbl    rINST_HI,rINST_FULL
5938    andb      $0xf,rINST_LO            # rINST_FULL<- A
5939    SET_VREG_WORD(%ecx,rINST_FULL,0)    # v[A+0]<- lsw
5940    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[A+1]<- msw
5941    FETCH_INST_WORD(2)
5942    ADVANCE_PC(2)
5943    GOTO_NEXT
5944
5945/* ------------------------------ */
5946    .balign 64
5947.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
5948/* File: x86/OP_IGET_OBJECT_QUICK.S */
5949/* File: x86/OP_IGET_QUICK.S */
5950    /* For: iget-quick, iget-object-quick */
5951    /* op vA, vB, offset@CCCC */
5952    movzbl    rINST_HI,%ecx             # ecx<- BA
5953    sarl      $4,%ecx                  # ecx<- B
5954    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5955    movzwl    2(rPC),%eax               # eax<- field byte offset
5956    cmpl      $0,%ecx                  # is object null?
5957    je        common_errNullObject
5958    movl      (%ecx,%eax,1),%eax
5959    movzbl    rINST_HI,%ecx
5960    FETCH_INST_WORD(2)
5961    ADVANCE_PC(2)
5962    andb      $0xf,%cl                 # rINST_FULL<- A
5963    SET_VREG  (%eax,%ecx)               # fp[A]<- result
5964    GOTO_NEXT
5965
5966
5967/* ------------------------------ */
5968    .balign 64
5969.L_OP_IPUT_QUICK: /* 0xf5 */
5970/* File: x86/OP_IPUT_QUICK.S */
5971    /* For: iput-quick, iput-object-quick */
5972    /* op vA, vB, offset@CCCC */
5973    movzbl    rINST_HI,%ecx             # ecx<- BA
5974    sarl      $4,%ecx                  # ecx<- B
5975    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5976    movzbl    rINST_HI,rINST_FULL
5977    andb      $0xf,rINST_LO            # rINST_FULL<- A
5978    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- v[A]
5979    movzwl    2(rPC),%eax               # eax<- field byte offset
5980    testl     %ecx,%ecx                  # is object null?
5981    je        common_errNullObject
5982    movl      rINST_FULL,(%ecx,%eax,1)
5983    FETCH_INST_WORD(2)
5984    ADVANCE_PC(2)
5985    GOTO_NEXT
5986
5987/* ------------------------------ */
5988    .balign 64
5989.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
5990/* File: x86/OP_IPUT_WIDE_QUICK.S */
5991    /* For: iput-wide-quick */
5992    /* op vA, vB, offset@CCCC */
5993    movzbl    rINST_HI,%ecx             # ecx<- BA
5994    sarl      $4,%ecx                  # ecx<- B
5995    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
5996    movzwl    2(rPC),%eax               # eax<- field byte offset
5997    testl      %ecx,%ecx                # is object null?
5998    je        common_errNullObject
5999    leal      (%ecx,%eax,1),%ecx        # ecx<- Address of 64-bit target
6000    movzbl    rINST_HI,rINST_FULL
6001    andb      $0xf,rINST_LO            # rINST_FULL<- A
6002    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- lsw
6003    GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
6004    movl      %eax,(%ecx)
6005    movl      rINST_FULL,4(%ecx)
6006    FETCH_INST_WORD(2)
6007    ADVANCE_PC(2)
6008    GOTO_NEXT
6009
6010/* ------------------------------ */
6011    .balign 64
6012.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
6013/* File: x86/OP_IPUT_OBJECT_QUICK.S */
6014/* File: x86/OP_IPUT_QUICK.S */
6015    /* For: iput-quick, iput-object-quick */
6016    /* op vA, vB, offset@CCCC */
6017    movzbl    rINST_HI,%ecx             # ecx<- BA
6018    sarl      $4,%ecx                  # ecx<- B
6019    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
6020    movzbl    rINST_HI,rINST_FULL
6021    andb      $0xf,rINST_LO            # rINST_FULL<- A
6022    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- v[A]
6023    movzwl    2(rPC),%eax               # eax<- field byte offset
6024    testl     %ecx,%ecx                  # is object null?
6025    je        common_errNullObject
6026    movl      rINST_FULL,(%ecx,%eax,1)
6027    FETCH_INST_WORD(2)
6028    ADVANCE_PC(2)
6029    GOTO_NEXT
6030
6031
6032/* ------------------------------ */
6033    .balign 64
6034.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
6035/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6036    /*
6037     * Handle an optimized virtual method call.
6038     *
6039     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6040     */
6041    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6042    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6043    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
6044    movzwl    2(rPC),%ecx               # ecx<- BBBB
6045    .if     (!0)
6046    andl      $0xf,%eax                # eax<- C (or stays CCCC)
6047    .endif
6048    GET_VREG(%eax,%eax)                 # eax<- vC ("this" ptr)
6049    testl     %eax,%eax                 # null?
6050    je        common_errNullObject      # yep, throw exception
6051    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6052    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6053    EXPORT_PC()                         # might throw later - get ready
6054    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
6055    jmp       common_invokeMethodNoRange
6056
6057/* ------------------------------ */
6058    .balign 64
6059.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
6060/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
6061/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
6062    /*
6063     * Handle an optimized virtual method call.
6064     *
6065     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
6066     */
6067    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6068    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6069    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
6070    movzwl    2(rPC),%ecx               # ecx<- BBBB
6071    .if     (!1)
6072    andl      $0xf,%eax                # eax<- C (or stays CCCC)
6073    .endif
6074    GET_VREG(%eax,%eax)                 # eax<- vC ("this" ptr)
6075    testl     %eax,%eax                 # null?
6076    je        common_errNullObject      # yep, throw exception
6077    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
6078    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
6079    EXPORT_PC()                         # might throw later - get ready
6080    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
6081    jmp       common_invokeMethodRange
6082
6083
6084/* ------------------------------ */
6085    .balign 64
6086.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
6087/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6088    /*
6089     * Handle an optimized "super" method call.
6090     *
6091     * for: [opt] invoke-super-quick, invoke-super-quick/range
6092     */
6093    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6094    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6095    GET_GLUE(%ecx)
6096    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
6097    movl      offGlue_method(%ecx),%ecx # ecx<- current method
6098    .if       (!0)
6099    andl      $0xf,%eax                # eax<- D (or stays CCCC)
6100    .endif
6101    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6102    GET_VREG(%eax,%eax)                 # eax<- "this"
6103    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6104    testl     %eax,%eax                 # null "this"?
6105    je        common_errNullObject      # "this" is null, throw exception
6106    movzwl    2(rPC),%eax               # eax<- BBBB
6107    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6108    EXPORT_PC()
6109    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
6110    jmp       common_invokeMethodNoRange
6111
6112/* ------------------------------ */
6113    .balign 64
6114.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
6115/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
6116/* File: x86/OP_INVOKE_SUPER_QUICK.S */
6117    /*
6118     * Handle an optimized "super" method call.
6119     *
6120     * for: [opt] invoke-super-quick, invoke-super-quick/range
6121     */
6122    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
6123    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
6124    GET_GLUE(%ecx)
6125    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
6126    movl      offGlue_method(%ecx),%ecx # ecx<- current method
6127    .if       (!1)
6128    andl      $0xf,%eax                # eax<- D (or stays CCCC)
6129    .endif
6130    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6131    GET_VREG(%eax,%eax)                 # eax<- "this"
6132    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
6133    testl     %eax,%eax                 # null "this"?
6134    je        common_errNullObject      # "this" is null, throw exception
6135    movzwl    2(rPC),%eax               # eax<- BBBB
6136    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
6137    EXPORT_PC()
6138    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
6139    jmp       common_invokeMethodRange
6140
6141
6142/* ------------------------------ */
6143    .balign 64
6144.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
6145    /* (stub) */
6146    GET_GLUE(%ecx)
6147    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
6148    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
6149    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6150    call      dvmMterp_OP_IPUT_OBJECT_VOLATILE     # do the real work
6151    GET_GLUE(%ecx)
6152    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
6153    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
6154    FETCH_INST()
6155    GOTO_NEXT
6156/* ------------------------------ */
6157    .balign 64
6158.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
6159    /* (stub) */
6160    GET_GLUE(%ecx)
6161    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
6162    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
6163    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6164    call      dvmMterp_OP_SGET_OBJECT_VOLATILE     # do the real work
6165    GET_GLUE(%ecx)
6166    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
6167    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
6168    FETCH_INST()
6169    GOTO_NEXT
6170/* ------------------------------ */
6171    .balign 64
6172.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
6173    /* (stub) */
6174    GET_GLUE(%ecx)
6175    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
6176    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
6177    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
6178    call      dvmMterp_OP_SPUT_OBJECT_VOLATILE     # do the real work
6179    GET_GLUE(%ecx)
6180    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
6181    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
6182    FETCH_INST()
6183    GOTO_NEXT
6184/* ------------------------------ */
6185    .balign 64
6186.L_OP_UNUSED_FF: /* 0xff */
6187/* File: x86/OP_UNUSED_FF.S */
6188/* File: x86/unused.S */
6189    jmp     common_abort
6190
6191
6192
6193    .balign 64
6194    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
6195    .global dvmAsmInstructionEnd
6196dvmAsmInstructionEnd:
6197
6198/*
6199 * ===========================================================================
6200 *  Sister implementations
6201 * ===========================================================================
6202 */
6203    .global dvmAsmSisterStart
6204    .type   dvmAsmSisterStart, %function
6205    .text
6206    .balign 4
6207dvmAsmSisterStart:
6208
6209/* continuation for OP_CONST_STRING */
6210
6211/* This is the less common path, so we'll redo some work
6212   here rather than force spills on the common path */
6213.LOP_CONST_STRING_resolve:
6214    GET_GLUE(%eax)
6215    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
6216    EXPORT_PC()
6217    movl     offGlue_method(%eax),%eax # eax<- glue->method
6218    movzwl   2(rPC),%ecx               # ecx<- BBBB
6219    movl     offMethod_clazz(%eax),%eax
6220    SPILL(rPC)
6221    movl     %ecx,OUT_ARG1(%esp)
6222    movl     %eax,OUT_ARG0(%esp)
6223    call     dvmResolveString          # go resolve
6224    UNSPILL(rPC)
6225    testl    %eax,%eax                 # failed?
6226    je       common_exceptionThrown
6227    SET_VREG(%eax,rINST_FULL)
6228    FETCH_INST_WORD(2)
6229    ADVANCE_PC(2)
6230    GOTO_NEXT
6231
6232/* continuation for OP_CONST_STRING_JUMBO */
6233
6234/* This is the less common path, so we'll redo some work
6235   here rather than force spills on the common path */
6236.LOP_CONST_STRING_JUMBO_resolve:
6237    GET_GLUE(%eax)
6238    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
6239    EXPORT_PC()
6240    movl     offGlue_method(%eax),%eax # eax<- glue->method
6241    movl     2(rPC),%ecx               # ecx<- BBBBBBBB
6242    movl     offMethod_clazz(%eax),%eax
6243    SPILL(rPC)
6244    movl     %ecx,OUT_ARG1(%esp)
6245    movl     %eax,OUT_ARG0(%esp)
6246    call     dvmResolveString          # go resolve
6247    UNSPILL(rPC)
6248    testl    %eax,%eax                 # failed?
6249    je       common_exceptionThrown
6250    SET_VREG(%eax,rINST_FULL)
6251    FETCH_INST_WORD(3)
6252    ADVANCE_PC(3)
6253    GOTO_NEXT
6254
6255/* continuation for OP_CONST_CLASS */
6256
6257/* This is the less common path, so we'll redo some work
6258   here rather than force spills on the common path */
6259.LOP_CONST_CLASS_resolve:
6260    GET_GLUE(%eax)
6261    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
6262    EXPORT_PC()
6263    movl     offGlue_method(%eax),%eax # eax<- glue->method
6264    movl     $1,OUT_ARG2(%esp)        # true
6265    movzwl   2(rPC),%ecx               # ecx<- BBBB
6266    movl     offMethod_clazz(%eax),%eax
6267    SPILL(rPC)
6268    movl     %ecx,OUT_ARG1(%esp)
6269    movl     %eax,OUT_ARG0(%esp)
6270    call     dvmResolveClass           # go resolve
6271    UNSPILL(rPC)
6272    testl    %eax,%eax                 # failed?
6273    je       common_exceptionThrown
6274    SET_VREG(%eax,rINST_FULL)
6275    FETCH_INST_WORD(2)
6276    ADVANCE_PC(2)
6277    GOTO_NEXT
6278
6279/* continuation for OP_MONITOR_ENTER */
6280
6281.LOP_MONITOR_ENTER_continue:
6282    SPILL(rPC)                          # have to - caller save
6283    movl    %ecx,OUT_ARG0(%esp)
6284    movl    %eax,OUT_ARG1(%esp)
6285    call    dvmLockObject               # dvmLockObject(self,object)
6286    UNSPILL(rPC)
6287#ifdef WITH_DEADLOCK_PREDICTION
6288    GET_GLUE(%ecx)
6289    movl    offGlueSelf(%ecx),%ecx      # ecx<- glue->self
6290    movl    offThread_exception(%ecx),%eax
6291    testl   %eax,%eax
6292    jne     common_exceptionThrown
6293#endif
6294    ADVANCE_PC(1)
6295    GOTO_NEXT
6296
6297/* continuation for OP_MONITOR_EXIT */
6298
6299.LOP_MONITOR_EXIT_continue:
6300    call    dvmUnlockObject             # unlock(self,obj)
6301    UNSPILL(rPC)
6302    FETCH_INST_WORD(1)
6303    testl   %eax,%eax                   # success?
6304    ADVANCE_PC(1)
6305    je      common_exceptionThrown      # no, exception pending
6306    GOTO_NEXT
6307.LOP_MONITOR_EXIT_errNullObject:
6308    ADVANCE_PC(1)                       # advance before throw
6309    jmp     common_errNullObject
6310
6311/* continuation for OP_CHECK_CAST */
6312
6313    /*
6314     * Trivial test failed, need to perform full check.  This is common.
6315     *  ecx holds obj->clazz
6316     *  eax holds class resolved from BBBB
6317     *  rINST_FULL holds object
6318     */
6319.LOP_CHECK_CAST_fullcheck:
6320    movl    %eax,OUT_ARG1(%esp)
6321    movl    %ecx,OUT_ARG0(%esp)
6322    SPILL(rPC)
6323    call    dvmInstanceofNonTrivial     # eax<- boolean result
6324    UNSPILL(rPC)
6325    testl   %eax,%eax                   # failed?
6326    jne     .LOP_CHECK_CAST_okay            # no, success
6327
6328    # A cast has failed.  We need to throw a ClassCastException with the
6329    # class of the object that failed to be cast.
6330    EXPORT_PC()
6331    movl    offObject_clazz(rINST_FULL),%ecx  # ecx<- obj->clazz
6332    movl    $.LstrClassCastException,%eax
6333    movl    offClassObject_descriptor(%ecx),%ecx
6334    movl    %eax,OUT_ARG0(%esp)     # arg0<- message
6335    movl    %ecx,OUT_ARG1(%esp)     # arg1<- obj->clazz->descriptor
6336    SPILL(rPC)
6337    call    dvmThrowExceptionWithClassMessage
6338    UNSPILL(rPC)
6339    jmp     common_exceptionThrown
6340
6341    /*
6342     * Resolution required.  This is the least-likely path, and we're
6343     * going to have to recreate some data.
6344     *
6345     *  rINST_FULL holds object
6346     */
6347.LOP_CHECK_CAST_resolve:
6348    GET_GLUE(%ecx)
6349    EXPORT_PC()
6350    movzwl  2(rPC),%eax                # eax<- BBBB
6351    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6352    movl    %eax,OUT_ARG1(%esp)        # arg1<- BBBB
6353    movl    offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
6354    movl    $0,OUT_ARG2(%esp)         # arg2<- false
6355    movl    %ecx,OUT_ARG0(%esp)        # arg0<- method->clazz
6356    SPILL(rPC)
6357    call    dvmResolveClass            # eax<- resolved ClassObject ptr
6358    UNSPILL(rPC)
6359    testl   %eax,%eax                  # got null?
6360    je      common_exceptionThrown     # yes, handle exception
6361    movl    offObject_clazz(rINST_FULL),%ecx  # ecx<- obj->clazz
6362    jmp     .LOP_CHECK_CAST_resolved       # pick up where we left off
6363
6364/* continuation for OP_INSTANCE_OF */
6365
6366    /*
6367     * Trivial test failed, need to perform full check.  This is common.
6368     *  eax holds obj->clazz
6369     *  ecx holds class resolved from BBBB
6370     *  rINST_HI has BA
6371     *  rPC already spilled
6372     */
6373.LOP_INSTANCE_OF_fullcheck:
6374    movl    %eax,OUT_ARG0(%esp)
6375    movl    %ecx,OUT_ARG1(%esp)
6376    call    dvmInstanceofNonTrivial     # eax<- boolean result
6377    # fall through to OP_INSTANCE_OF_store
6378
6379    /*
6380     * eax holds boolean result
6381     * rINST_HI holds BA
6382     */
6383.LOP_INSTANCE_OF_store:
6384    UNSPILL(rPC)
6385    movzbl  rINST_HI,%ecx               # ecx<- BA
6386    FETCH_INST_WORD(2)
6387    andb    $0xf,%cl                   # ecl<- A
6388    ADVANCE_PC(2)
6389    SET_VREG(%eax,%ecx)                 # vA<- eax
6390    GOTO_NEXT
6391
6392    /*
6393     * Trivial test succeeded, save and bail.
6394     *  r9 holds A
6395     */
6396.LOP_INSTANCE_OF_trivial:
6397    UNSPILL(rPC)
6398    movzbl  rINST_HI,%ecx               # ecx<- BA
6399    FETCH_INST_WORD(2)
6400    andb    $0xf,%cl                   # ecl<- A
6401    ADVANCE_PC(2)
6402    movl    $1,%eax
6403    SET_VREG(%eax,%ecx)                  # vA<- true
6404    GOTO_NEXT
6405
6406    /*
6407     * Resolution required.  This is the least-likely path.
6408     *
6409     *  rPC holds BBBB
6410     *  rINST_HI holds BA
6411     */
6412.LOP_INSTANCE_OF_resolve:
6413    movl    rPC,OUT_ARG1(%esp)          # arg1<- BBBB
6414    GET_GLUE(%ecx)
6415    UNSPILL(rPC)
6416    movl    offGlue_method(%ecx),%ecx
6417    movl    $1,OUT_ARG2(%esp)          # arg2<- true
6418    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6419    EXPORT_PC()
6420    movl    %ecx,OUT_ARG0(%esp)         # arg0<- method->clazz
6421    call    dvmResolveClass             # eax<- resolved ClassObject ptr
6422    UNSPILL(rPC)
6423    testl   %eax,%eax                   # success?
6424    je      common_exceptionThrown      # no, handle exception
6425/* Now, we need to sync up with fast path.  We need eax to
6426 * hold the obj->clazz, and ecx to hold the resolved class
6427 */
6428    movl    %eax,%ecx                   # ecx<- resolved class
6429    movzbl  rINST_HI,%eax               # eax<- BA
6430    sarl    $4,%eax                    # eax<- B
6431    GET_VREG(%eax,%eax)                 # eax<- vB (obj)
6432    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
6433    jmp     .LOP_INSTANCE_OF_resolved
6434
6435/* continuation for OP_NEW_INSTANCE */
6436
6437.LOP_NEW_INSTANCE_initialized:  # on entry, ecx<- class
6438    /* TODO: remove test for interface/abstract, now done in verifier */
6439    testl     $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
6440    movl      $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
6441    jne       .LOP_NEW_INSTANCE_abstract
6442.LOP_NEW_INSTANCE_finish: # ecx=class
6443    movl     %ecx,OUT_ARG0(%esp)
6444    call     dvmAllocObject             # eax<- new object
6445    UNSPILL(rPC)
6446    movl     rINST_FULL,%ecx
6447    FETCH_INST_WORD(2)
6448    testl    %eax,%eax                  # success?
6449    je       common_exceptionThrown     # no, bail out
6450    SET_VREG(%eax,%ecx)
6451    ADVANCE_PC(2)
6452    GOTO_NEXT
6453
6454    /*
6455     * Class initialization required.
6456     *
6457     *  ecx holds class object
6458     */
6459.LOP_NEW_INSTANCE_needinit:
6460    SPILL_TMP(%ecx)                     # save object
6461    movl    %ecx,OUT_ARG0(%esp)
6462    call    dvmInitClass                # initialize class
6463    UNSPILL_TMP(%ecx)                   # restore object
6464    testl   %eax,%eax                   # success?
6465    jne     .LOP_NEW_INSTANCE_initialized     # success, continue
6466    UNSPILL(rPC)                        # failed, restore PC
6467    jmp     common_exceptionThrown      # go deal with init exception
6468
6469    /*
6470     * Resolution required.  This is the least-likely path.
6471     *
6472     */
6473.LOP_NEW_INSTANCE_resolve:
6474    GET_GLUE(%ecx)
6475    movzwl  2(rPC),%eax
6476    movl    offGlue_method(%ecx),%ecx   # ecx<- glue->method
6477    movl    %eax,OUT_ARG1(%esp)
6478    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
6479    movl    $0,OUT_ARG2(%esp)
6480    movl    %ecx,OUT_ARG0(%esp)
6481    call    dvmResolveClass             # call(clazz,off,flags)
6482    movl    %eax,%ecx                   # ecx<- resolved ClassObject ptr
6483    testl   %ecx,%ecx                   # success?
6484    jne     .LOP_NEW_INSTANCE_resolved        # good to go
6485    UNSPILL(rPC)
6486    jmp     common_exceptionThrown      # no, handle exception
6487
6488    /*
6489     * TODO: remove this
6490     * We can't instantiate an abstract class or interface, so throw an
6491     * InstantiationError with the class descriptor as the message.
6492     *
6493     *  ecx holds class object
6494     */
6495.LOP_NEW_INSTANCE_abstract:
6496    movl    offClassObject_descriptor(%ecx),%eax
6497    movl    $.LstrInstantiationError,OUT_ARG0(%esp)
6498    movl    %eax,OUT_ARG1(%esp)
6499    call    dvmThrowExceptionWithClassMessage
6500    UNSPILL(rPC)
6501    jmp     common_exceptionThrown
6502
6503/* continuation for OP_NEW_ARRAY */
6504
6505    /*
6506     * Resolve class.  (This is an uncommon case.)
6507     *  ecx holds class (null here)
6508     *  eax holds array length (vB)
6509     */
6510.LOP_NEW_ARRAY_resolve:
6511    GET_GLUE(%ecx)
6512    SPILL_TMP(%eax)                    # save array length
6513    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
6514    movzwl  2(rPC),%eax                # eax<- CCCC
6515    movl    offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
6516    movl    %eax,OUT_ARG1(%esp)
6517    movl    $0,OUT_ARG2(%esp)
6518    movl    %ecx,OUT_ARG0(%esp)
6519    SPILL(rPC)
6520    call    dvmResolveClass            # eax<- call(clazz,ref,flag)
6521    UNSPILL(rPC)
6522    movl    %eax,%ecx
6523    UNSPILL_TMP(%eax)
6524    testl   %ecx,%ecx                  # successful resolution?
6525    je      common_exceptionThrown     # no, bail.
6526# fall through to OP_NEW_ARRAY_finish
6527
6528    /*
6529     * Finish allocation
6530     *
6531     * ecx holds class
6532     * eax holds array length (vB)
6533     */
6534.LOP_NEW_ARRAY_finish:
6535    movl    %ecx,OUT_ARG0(%esp)
6536    movl    %eax,OUT_ARG1(%esp)
6537    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
6538    SPILL(rPC)
6539    call    dvmAllocArrayByClass    # eax<- call(clazz,length,flags)
6540    UNSPILL(rPC)
6541    testl   %eax,%eax               # failed?
6542    je      common_exceptionThrown  # yup - go handle
6543    movl    rINST_FULL,%ecx
6544    FETCH_INST_WORD(2)
6545    SET_VREG(%eax,%ecx)
6546    ADVANCE_PC(2)
6547    GOTO_NEXT
6548
6549/* continuation for OP_FILLED_NEW_ARRAY */
6550
6551.LOP_FILLED_NEW_ARRAY_more:
6552    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6553    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6554    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6555    UNSPILL(rPC)
6556    testl   %eax,%eax                         # null?
6557    je      common_exceptionThrown            # yes, handle it
6558
6559       # note: fall through to .LOP_FILLED_NEW_ARRAY_continue
6560
6561    /*
6562     * On entry:
6563     *    eax holds array class [r0]
6564     *    rINST_FULL holds AA or BB [r10]
6565     *    ecx is scratch
6566     *    rPC is valid, but has been spilled
6567     */
6568.LOP_FILLED_NEW_ARRAY_continue:
6569    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6570    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6571    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6572    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6573    cmpb    $'I',%cl                             # supported?
6574    je      1f
6575    cmpb    $'L',%cl
6576    je      1f
6577    cmpb    $'[',%cl
6578    jne      .LOP_FILLED_NEW_ARRAY_notimpl                  # no, not handled yet
65791:
6580    .if      (!0)
6581    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
6582    sarl    $4,rINST_FULL
6583    .endif
6584    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
6585    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
6586    UNSPILL(rPC)
6587    GET_GLUE(%ecx)
6588    testl   %eax,%eax                             # alloc successful?
6589    je      common_exceptionThrown                # no, handle exception
6590    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6591    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6592    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6593
6594/* at this point:
6595 *     eax is pointer to tgt
6596 *     rINST_FULL is length
6597 *     ecx is FEDC or CCCC
6598 *     TMP_SPILL is BA
6599 *     rPC is valid, but spilled
6600 *  We now need to copy values from registers into the array
6601 */
6602
6603    .if 0
6604    # set up src pointer
6605    SPILL(rFP)     # esi
6606    SPILL(rIBASE)   # edi
6607    movl    %eax,%edi         # set up dst ptr
6608    leal    (rFP,%ecx,4),%esi # set up src ptr
6609    movl    rINST_FULL,%ecx   # load count register
6610    FETCH_INST_WORD(3)
6611    rep
6612    movsd
6613    UNSPILL(rIBASE)
6614    UNSPILL(rFP)
6615    .else
6616    testl  rINST_FULL,rINST_FULL
6617    je     4f
6618    UNSPILL_TMP(rPC)
6619    andl   $0x0f,rPC            # rPC<- 0000000A
6620    sall   $16,rPC              # rPC<- 000A0000
6621    orl    %ecx,rPC              # rpc<- 000AFEDC
66223:
6623    movl   $0xf,%ecx
6624    andl   rPC,%ecx           # ecx<- next reg to load
6625    GET_VREG(%ecx,%ecx)
6626    shrl   $4,rPC
6627    leal   4(%eax),%eax
6628    movl   %ecx,-4(%eax)
6629    sub    $1,rINST_FULL
6630    jne    3b
66314:
6632    UNSPILL(rPC)
6633    FETCH_INST_WORD(3)
6634    .endif
6635
6636    ADVANCE_PC(3)
6637    GOTO_NEXT
6638
6639
6640    /*
6641     * Throw an exception indicating that we have not implemented this
6642     * mode of filled-new-array.
6643     */
6644.LOP_FILLED_NEW_ARRAY_notimpl:
6645    movl    $.LstrInternalError,%eax
6646    movl    %eax,OUT_ARG0(%esp)
6647    movl    $.LstrFilledNewArrayNotImpl,%eax
6648    movl    %eax,OUT_ARG1(%esp)
6649    call    dvmThrowException
6650    UNSPILL(rPC)
6651    jmp     common_exceptionThrown
6652
6653/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
6654
6655.LOP_FILLED_NEW_ARRAY_RANGE_more:
6656    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
6657    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
6658    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
6659    UNSPILL(rPC)
6660    testl   %eax,%eax                         # null?
6661    je      common_exceptionThrown            # yes, handle it
6662
6663       # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue
6664
6665    /*
6666     * On entry:
6667     *    eax holds array class [r0]
6668     *    rINST_FULL holds AA or BB [r10]
6669     *    ecx is scratch
6670     *    rPC is valid, but has been spilled
6671     */
6672.LOP_FILLED_NEW_ARRAY_RANGE_continue:
6673    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
6674    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
6675    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
6676    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
6677    cmpb    $'I',%cl                             # supported?
6678    je      1f
6679    cmpb    $'L',%cl
6680    je      1f
6681    cmpb    $'[',%cl
6682    jne      .LOP_FILLED_NEW_ARRAY_RANGE_notimpl                  # no, not handled yet
66831:
6684    .if      (!1)
6685    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
6686    sarl    $4,rINST_FULL
6687    .endif
6688    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
6689    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
6690    UNSPILL(rPC)
6691    GET_GLUE(%ecx)
6692    testl   %eax,%eax                             # alloc successful?
6693    je      common_exceptionThrown                # no, handle exception
6694    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
6695    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
6696    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents
6697
6698/* at this point:
6699 *     eax is pointer to tgt
6700 *     rINST_FULL is length
6701 *     ecx is FEDC or CCCC
6702 *     TMP_SPILL is BA
6703 *     rPC is valid, but spilled
6704 *  We now need to copy values from registers into the array
6705 */
6706
6707    .if 1
6708    # set up src pointer
6709    SPILL(rFP)     # esi
6710    SPILL(rIBASE)   # edi
6711    movl    %eax,%edi         # set up dst ptr
6712    leal    (rFP,%ecx,4),%esi # set up src ptr
6713    movl    rINST_FULL,%ecx   # load count register
6714    FETCH_INST_WORD(3)
6715    rep
6716    movsd
6717    UNSPILL(rIBASE)
6718    UNSPILL(rFP)
6719    .else
6720    testl  rINST_FULL,rINST_FULL
6721    je     4f
6722    UNSPILL_TMP(rPC)
6723    andl   $0x0f,rPC            # rPC<- 0000000A
6724    sall   $16,rPC              # rPC<- 000A0000
6725    orl    %ecx,rPC              # rpc<- 000AFEDC
67263:
6727    movl   $0xf,%ecx
6728    andl   rPC,%ecx           # ecx<- next reg to load
6729    GET_VREG(%ecx,%ecx)
6730    shrl   $4,rPC
6731    leal   4(%eax),%eax
6732    movl   %ecx,-4(%eax)
6733    sub    $1,rINST_FULL
6734    jne    3b
67354:
6736    UNSPILL(rPC)
6737    FETCH_INST_WORD(3)
6738    .endif
6739
6740    ADVANCE_PC(3)
6741    GOTO_NEXT
6742
6743
6744    /*
6745     * Throw an exception indicating that we have not implemented this
6746     * mode of filled-new-array.
6747     */
6748.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
6749    movl    $.LstrInternalError,%eax
6750    movl    %eax,OUT_ARG0(%esp)
6751    movl    $.LstrFilledNewArrayNotImpl,%eax
6752    movl    %eax,OUT_ARG1(%esp)
6753    call    dvmThrowException
6754    UNSPILL(rPC)
6755    jmp     common_exceptionThrown
6756
6757/* continuation for OP_CMPL_FLOAT */
6758
6759.LOP_CMPL_FLOAT_isNaN:
6760    movl      $-1,%ecx
6761    jmp       .LOP_CMPL_FLOAT_finish
6762
6763/* continuation for OP_CMPG_FLOAT */
6764
6765.LOP_CMPG_FLOAT_isNaN:
6766    movl      $1,%ecx
6767    jmp       .LOP_CMPG_FLOAT_finish
6768
6769/* continuation for OP_CMPL_DOUBLE */
6770
6771.LOP_CMPL_DOUBLE_isNaN:
6772    movl      $-1,%ecx
6773    jmp       .LOP_CMPL_DOUBLE_finish
6774
6775/* continuation for OP_CMPG_DOUBLE */
6776
6777.LOP_CMPG_DOUBLE_isNaN:
6778    movl      $1,%ecx
6779    jmp       .LOP_CMPG_DOUBLE_finish
6780
6781/* continuation for OP_CMP_LONG */
6782
6783.LOP_CMP_LONG_bigger:
6784    UNSPILL(rPC)
6785    movl      $1,%ecx
6786    jmp       .LOP_CMP_LONG_finish
6787.LOP_CMP_LONG_smaller:
6788    UNSPILL(rPC)
6789    movl      $-1,%ecx
6790.LOP_CMP_LONG_finish:
6791    SET_VREG(%ecx,rINST_FULL)
6792    FETCH_INST_WORD(2)
6793    ADVANCE_PC(2)
6794    GOTO_NEXT
6795
6796/* continuation for OP_AGET_WIDE */
6797
6798.LOP_AGET_WIDE_finish:
6799    leal      offArrayObject_contents(%eax,%ecx,8),%eax
6800    movl      (%eax),%ecx
6801    movl      4(%eax),%eax
6802    SET_VREG_WORD(%ecx,rINST_FULL,0)
6803    SET_VREG_WORD(%eax,rINST_FULL,1)
6804    FETCH_INST_WORD(2)
6805    ADVANCE_PC(2)
6806    GOTO_NEXT
6807
6808/* continuation for OP_APUT_WIDE */
6809
6810.LOP_APUT_WIDE_finish:
6811    leal      offArrayObject_contents(%eax,%ecx,8),%eax
6812    GET_VREG_WORD(%ecx,rINST_FULL,0)
6813    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)
6814    movl      rINST_FULL,4(%eax)
6815    FETCH_INST_WORD(2)
6816    movl      %ecx,(%eax)
6817    ADVANCE_PC(2)
6818    GOTO_NEXT
6819
6820/* continuation for OP_APUT_OBJECT */
6821
6822    /* On entry:
6823     *   eax<- array object
6824     *   ecx<- index
6825     *   rINST_FULL<- vAA
6826     */
6827.LOP_APUT_OBJECT_continue:
6828    leal      offArrayObject_contents(%eax,%ecx,4),%ecx
6829    testl     rINST_FULL,rINST_FULL     # storing null reference?
6830    je        .LOP_APUT_OBJECT_skip_check
6831    SPILL(rPC)
6832    SPILL_TMP(%ecx)
6833    movl      offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
6834    movl      offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
6835    movl      %eax,OUT_ARG1(%esp)
6836    movl      %ecx,OUT_ARG0(%esp)
6837    call      dvmCanPutArrayElement     # test object type vs. array type
6838    UNSPILL(rPC)
6839    UNSPILL_TMP(%ecx)
6840    testl     %eax,%eax
6841    je        common_errArrayStore
6842
6843.LOP_APUT_OBJECT_skip_check:
6844    movl      rINST_FULL,(%ecx)
6845    FETCH_INST_WORD(2)
6846    ADVANCE_PC(2)
6847    GOTO_NEXT
6848
6849/* continuation for OP_IGET */
6850
6851
6852.LOP_IGET_resolve:
6853    EXPORT_PC()
6854    SPILL(rPC)
6855    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6856    UNSPILL(rIBASE)
6857    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6858    SPILL_TMP(%ecx)                               # save object pointer across call
6859    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6860    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6861    UNSPILL_TMP(%ecx)
6862    UNSPILL(rPC)
6863    testl   %eax,%eax                             #  ... which returns InstrField ptr
6864    jne     .LOP_IGET_finish
6865    jmp     common_exceptionThrown
6866
6867.LOP_IGET_finish:
6868    /*
6869     * Currently:
6870     *   eax holds resolved field
6871     *   ecx holds object
6872     *   rIBASE is scratch, but needs to be unspilled
6873     *   rINST_FULL holds A
6874     */
6875    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6876    UNSPILL(rIBASE)
6877    testl   %ecx,%ecx                            # object null?
6878    je      common_errNullObject                 # object was null
6879    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
6880    movl    rINST_FULL,%eax                      # eax<- A
6881    FETCH_INST_WORD(2)
6882    SET_VREG(%ecx,%eax)
6883    ADVANCE_PC(2)
6884    GOTO_NEXT
6885
6886/* continuation for OP_IGET_WIDE */
6887
6888
6889.LOP_IGET_WIDE_resolve:
6890    EXPORT_PC()
6891    SPILL(rPC)
6892    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6893    UNSPILL(rIBASE)
6894    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6895    SPILL_TMP(%ecx)                               # save object pointer across call
6896    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6897    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6898    UNSPILL_TMP(%ecx)
6899    UNSPILL(rPC)
6900    testl   %eax,%eax                             #  ... which returns InstrField ptr
6901    jne     .LOP_IGET_WIDE_finish
6902    jmp     common_exceptionThrown
6903
6904.LOP_IGET_WIDE_finish:
6905    /*
6906     * Currently:
6907     *   eax holds resolved field
6908     *   ecx holds object
6909     *   rIBASE is scratch, but needs to be unspilled
6910     *   rINST_FULL holds A
6911     */
6912    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6913    UNSPILL(rIBASE)
6914    testl   %ecx,%ecx                            # object null?
6915    je      common_errNullObject                 # object was null
6916    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
6917    movl    (%eax),%ecx                          # ecx<- lsw
6918    movl    4(%eax),%eax                         # eax<- msw
6919    SET_VREG_WORD(%ecx,rINST_FULL,0)
6920    SET_VREG_WORD(%eax,rINST_FULL,1)
6921    FETCH_INST_WORD(2)
6922    ADVANCE_PC(2)
6923    GOTO_NEXT
6924
6925/* continuation for OP_IGET_OBJECT */
6926
6927
6928.LOP_IGET_OBJECT_resolve:
6929    EXPORT_PC()
6930    SPILL(rPC)
6931    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6932    UNSPILL(rIBASE)
6933    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6934    SPILL_TMP(%ecx)                               # save object pointer across call
6935    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6936    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6937    UNSPILL_TMP(%ecx)
6938    UNSPILL(rPC)
6939    testl   %eax,%eax                             #  ... which returns InstrField ptr
6940    jne     .LOP_IGET_OBJECT_finish
6941    jmp     common_exceptionThrown
6942
6943.LOP_IGET_OBJECT_finish:
6944    /*
6945     * Currently:
6946     *   eax holds resolved field
6947     *   ecx holds object
6948     *   rIBASE is scratch, but needs to be unspilled
6949     *   rINST_FULL holds A
6950     */
6951    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6952    UNSPILL(rIBASE)
6953    testl   %ecx,%ecx                            # object null?
6954    je      common_errNullObject                 # object was null
6955    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
6956    movl    rINST_FULL,%eax                      # eax<- A
6957    FETCH_INST_WORD(2)
6958    SET_VREG(%ecx,%eax)
6959    ADVANCE_PC(2)
6960    GOTO_NEXT
6961
6962/* continuation for OP_IGET_BOOLEAN */
6963
6964
6965.LOP_IGET_BOOLEAN_resolve:
6966    EXPORT_PC()
6967    SPILL(rPC)
6968    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
6969    UNSPILL(rIBASE)
6970    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
6971    SPILL_TMP(%ecx)                               # save object pointer across call
6972    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
6973    call    dvmResolveInstField                   #  ... to dvmResolveInstField
6974    UNSPILL_TMP(%ecx)
6975    UNSPILL(rPC)
6976    testl   %eax,%eax                             #  ... which returns InstrField ptr
6977    jne     .LOP_IGET_BOOLEAN_finish
6978    jmp     common_exceptionThrown
6979
6980.LOP_IGET_BOOLEAN_finish:
6981    /*
6982     * Currently:
6983     *   eax holds resolved field
6984     *   ecx holds object
6985     *   rIBASE is scratch, but needs to be unspilled
6986     *   rINST_FULL holds A
6987     */
6988    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
6989    UNSPILL(rIBASE)
6990    testl   %ecx,%ecx                            # object null?
6991    je      common_errNullObject                 # object was null
6992    movzbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
6993    movl    rINST_FULL,%eax                      # eax<- A
6994    FETCH_INST_WORD(2)
6995    SET_VREG(%ecx,%eax)
6996    ADVANCE_PC(2)
6997    GOTO_NEXT
6998
6999/* continuation for OP_IGET_BYTE */
7000
7001
7002.LOP_IGET_BYTE_resolve:
7003    EXPORT_PC()
7004    SPILL(rPC)
7005    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7006    UNSPILL(rIBASE)
7007    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7008    SPILL_TMP(%ecx)                               # save object pointer across call
7009    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7010    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7011    UNSPILL_TMP(%ecx)
7012    UNSPILL(rPC)
7013    testl   %eax,%eax                             #  ... which returns InstrField ptr
7014    jne     .LOP_IGET_BYTE_finish
7015    jmp     common_exceptionThrown
7016
7017.LOP_IGET_BYTE_finish:
7018    /*
7019     * Currently:
7020     *   eax holds resolved field
7021     *   ecx holds object
7022     *   rIBASE is scratch, but needs to be unspilled
7023     *   rINST_FULL holds A
7024     */
7025    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7026    UNSPILL(rIBASE)
7027    testl   %ecx,%ecx                            # object null?
7028    je      common_errNullObject                 # object was null
7029    movsbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7030    movl    rINST_FULL,%eax                      # eax<- A
7031    FETCH_INST_WORD(2)
7032    SET_VREG(%ecx,%eax)
7033    ADVANCE_PC(2)
7034    GOTO_NEXT
7035
7036/* continuation for OP_IGET_CHAR */
7037
7038
7039.LOP_IGET_CHAR_resolve:
7040    EXPORT_PC()
7041    SPILL(rPC)
7042    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7043    UNSPILL(rIBASE)
7044    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7045    SPILL_TMP(%ecx)                               # save object pointer across call
7046    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7047    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7048    UNSPILL_TMP(%ecx)
7049    UNSPILL(rPC)
7050    testl   %eax,%eax                             #  ... which returns InstrField ptr
7051    jne     .LOP_IGET_CHAR_finish
7052    jmp     common_exceptionThrown
7053
7054.LOP_IGET_CHAR_finish:
7055    /*
7056     * Currently:
7057     *   eax holds resolved field
7058     *   ecx holds object
7059     *   rIBASE is scratch, but needs to be unspilled
7060     *   rINST_FULL holds A
7061     */
7062    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7063    UNSPILL(rIBASE)
7064    testl   %ecx,%ecx                            # object null?
7065    je      common_errNullObject                 # object was null
7066    movzwl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7067    movl    rINST_FULL,%eax                      # eax<- A
7068    FETCH_INST_WORD(2)
7069    SET_VREG(%ecx,%eax)
7070    ADVANCE_PC(2)
7071    GOTO_NEXT
7072
7073/* continuation for OP_IGET_SHORT */
7074
7075
7076.LOP_IGET_SHORT_resolve:
7077    EXPORT_PC()
7078    SPILL(rPC)
7079    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7080    UNSPILL(rIBASE)
7081    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7082    SPILL_TMP(%ecx)                               # save object pointer across call
7083    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7084    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7085    UNSPILL_TMP(%ecx)
7086    UNSPILL(rPC)
7087    testl   %eax,%eax                             #  ... which returns InstrField ptr
7088    jne     .LOP_IGET_SHORT_finish
7089    jmp     common_exceptionThrown
7090
7091.LOP_IGET_SHORT_finish:
7092    /*
7093     * Currently:
7094     *   eax holds resolved field
7095     *   ecx holds object
7096     *   rIBASE is scratch, but needs to be unspilled
7097     *   rINST_FULL holds A
7098     */
7099    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7100    UNSPILL(rIBASE)
7101    testl   %ecx,%ecx                            # object null?
7102    je      common_errNullObject                 # object was null
7103    movswl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
7104    movl    rINST_FULL,%eax                      # eax<- A
7105    FETCH_INST_WORD(2)
7106    SET_VREG(%ecx,%eax)
7107    ADVANCE_PC(2)
7108    GOTO_NEXT
7109
7110/* continuation for OP_IPUT */
7111
7112
7113.LOP_IPUT_resolve:
7114    EXPORT_PC()
7115    SPILL(rPC)
7116    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7117    UNSPILL(rIBASE)
7118    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7119    SPILL_TMP(%ecx)                               # save object pointer across call
7120    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7121    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7122    UNSPILL_TMP(%ecx)
7123    UNSPILL(rPC)
7124    testl   %eax,%eax                             #  ... which returns InstrField ptr
7125    jne     .LOP_IPUT_finish
7126    jmp     common_exceptionThrown
7127
7128.LOP_IPUT_finish:
7129    /*
7130     * Currently:
7131     *   eax holds resolved field
7132     *   ecx holds object
7133     *   rIBASE is scratch, but needs to be unspilled
7134     *   rINST_FULL holds A
7135     */
7136    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7137    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7138    UNSPILL(rIBASE)
7139    testl   %ecx,%ecx                            # object null?
7140    je      common_errNullObject                 # object was null
7141    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7142    FETCH_INST_WORD(2)
7143    ADVANCE_PC(2)
7144    GOTO_NEXT
7145
7146/* continuation for OP_IPUT_WIDE */
7147
7148
7149.LOP_IPUT_WIDE_resolve:
7150    EXPORT_PC()
7151    SPILL(rPC)
7152    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7153    UNSPILL(rIBASE)
7154    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7155    SPILL_TMP(%ecx)                               # save object pointer across call
7156    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7157    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7158    UNSPILL_TMP(%ecx)
7159    UNSPILL(rPC)
7160    testl   %eax,%eax                             #  ... which returns InstrField ptr
7161    jne     .LOP_IPUT_WIDE_finish
7162    jmp     common_exceptionThrown
7163
7164.LOP_IPUT_WIDE_finish:
7165    /*
7166     * Currently:
7167     *   eax holds resolved field
7168     *   ecx holds object
7169     *   rIBASE is scratch, but needs to be unspilled
7170     *   rINST_FULL holds A
7171     */
7172    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7173    UNSPILL(rIBASE)
7174    testl   %ecx,%ecx                            # object null?
7175    je      common_errNullObject                 # object was null
7176    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
7177    GET_VREG_WORD(%ecx,rINST_FULL,0)             # ecx<- lsw
7178    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)       # rINST_FULL<- msw
7179    movl    rINST_FULL,4(%eax)
7180    FETCH_INST_WORD(2)
7181    movl    %ecx,(%eax)
7182    ADVANCE_PC(2)
7183    GOTO_NEXT
7184
7185/* continuation for OP_IPUT_OBJECT */
7186
7187
7188.LOP_IPUT_OBJECT_resolve:
7189    EXPORT_PC()
7190    SPILL(rPC)
7191    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7192    UNSPILL(rIBASE)
7193    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7194    SPILL_TMP(%ecx)                               # save object pointer across call
7195    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7196    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7197    UNSPILL_TMP(%ecx)
7198    UNSPILL(rPC)
7199    testl   %eax,%eax                             #  ... which returns InstrField ptr
7200    jne     .LOP_IPUT_OBJECT_finish
7201    jmp     common_exceptionThrown
7202
7203.LOP_IPUT_OBJECT_finish:
7204    /*
7205     * Currently:
7206     *   eax holds resolved field
7207     *   ecx holds object
7208     *   rIBASE is scratch, but needs to be unspilled
7209     *   rINST_FULL holds A
7210     */
7211    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7212    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7213    UNSPILL(rIBASE)
7214    testl   %ecx,%ecx                            # object null?
7215    je      common_errNullObject                 # object was null
7216    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7217    FETCH_INST_WORD(2)
7218    ADVANCE_PC(2)
7219    GOTO_NEXT
7220
7221/* continuation for OP_IPUT_BOOLEAN */
7222
7223
7224.LOP_IPUT_BOOLEAN_resolve:
7225    EXPORT_PC()
7226    SPILL(rPC)
7227    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7228    UNSPILL(rIBASE)
7229    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7230    SPILL_TMP(%ecx)                               # save object pointer across call
7231    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7232    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7233    UNSPILL_TMP(%ecx)
7234    UNSPILL(rPC)
7235    testl   %eax,%eax                             #  ... which returns InstrField ptr
7236    jne     .LOP_IPUT_BOOLEAN_finish
7237    jmp     common_exceptionThrown
7238
7239.LOP_IPUT_BOOLEAN_finish:
7240    /*
7241     * Currently:
7242     *   eax holds resolved field
7243     *   ecx holds object
7244     *   rIBASE is scratch, but needs to be unspilled
7245     *   rINST_FULL holds A
7246     */
7247    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7248    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7249    UNSPILL(rIBASE)
7250    testl   %ecx,%ecx                            # object null?
7251    je      common_errNullObject                 # object was null
7252    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7253    FETCH_INST_WORD(2)
7254    ADVANCE_PC(2)
7255    GOTO_NEXT
7256
7257/* continuation for OP_IPUT_BYTE */
7258
7259
7260.LOP_IPUT_BYTE_resolve:
7261    EXPORT_PC()
7262    SPILL(rPC)
7263    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7264    UNSPILL(rIBASE)
7265    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7266    SPILL_TMP(%ecx)                               # save object pointer across call
7267    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7268    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7269    UNSPILL_TMP(%ecx)
7270    UNSPILL(rPC)
7271    testl   %eax,%eax                             #  ... which returns InstrField ptr
7272    jne     .LOP_IPUT_BYTE_finish
7273    jmp     common_exceptionThrown
7274
7275.LOP_IPUT_BYTE_finish:
7276    /*
7277     * Currently:
7278     *   eax holds resolved field
7279     *   ecx holds object
7280     *   rIBASE is scratch, but needs to be unspilled
7281     *   rINST_FULL holds A
7282     */
7283    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7284    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7285    UNSPILL(rIBASE)
7286    testl   %ecx,%ecx                            # object null?
7287    je      common_errNullObject                 # object was null
7288    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7289    FETCH_INST_WORD(2)
7290    ADVANCE_PC(2)
7291    GOTO_NEXT
7292
7293/* continuation for OP_IPUT_CHAR */
7294
7295
7296.LOP_IPUT_CHAR_resolve:
7297    EXPORT_PC()
7298    SPILL(rPC)
7299    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7300    UNSPILL(rIBASE)
7301    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7302    SPILL_TMP(%ecx)                               # save object pointer across call
7303    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7304    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7305    UNSPILL_TMP(%ecx)
7306    UNSPILL(rPC)
7307    testl   %eax,%eax                             #  ... which returns InstrField ptr
7308    jne     .LOP_IPUT_CHAR_finish
7309    jmp     common_exceptionThrown
7310
7311.LOP_IPUT_CHAR_finish:
7312    /*
7313     * Currently:
7314     *   eax holds resolved field
7315     *   ecx holds object
7316     *   rIBASE is scratch, but needs to be unspilled
7317     *   rINST_FULL holds A
7318     */
7319    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7320    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7321    UNSPILL(rIBASE)
7322    testl   %ecx,%ecx                            # object null?
7323    je      common_errNullObject                 # object was null
7324    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7325    FETCH_INST_WORD(2)
7326    ADVANCE_PC(2)
7327    GOTO_NEXT
7328
7329/* continuation for OP_IPUT_SHORT */
7330
7331
7332.LOP_IPUT_SHORT_resolve:
7333    EXPORT_PC()
7334    SPILL(rPC)
7335    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
7336    UNSPILL(rIBASE)
7337    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
7338    SPILL_TMP(%ecx)                               # save object pointer across call
7339    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
7340    call    dvmResolveInstField                   #  ... to dvmResolveInstField
7341    UNSPILL_TMP(%ecx)
7342    UNSPILL(rPC)
7343    testl   %eax,%eax                             #  ... which returns InstrField ptr
7344    jne     .LOP_IPUT_SHORT_finish
7345    jmp     common_exceptionThrown
7346
7347.LOP_IPUT_SHORT_finish:
7348    /*
7349     * Currently:
7350     *   eax holds resolved field
7351     *   ecx holds object
7352     *   rIBASE is scratch, but needs to be unspilled
7353     *   rINST_FULL holds A
7354     */
7355    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
7356    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
7357    UNSPILL(rIBASE)
7358    testl   %ecx,%ecx                            # object null?
7359    je      common_errNullObject                 # object was null
7360    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
7361    FETCH_INST_WORD(2)
7362    ADVANCE_PC(2)
7363    GOTO_NEXT
7364
7365/* continuation for OP_SGET */
7366
7367    /*
7368     * Go resolve the field
7369     */
7370.LOP_SGET_resolve:
7371    GET_GLUE(%ecx)
7372    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7373    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7374    EXPORT_PC()                                 # could throw, need to export
7375    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7376    SPILL(rPC)
7377    movl     %eax,OUT_ARG1(%esp)
7378    movl     %ecx,OUT_ARG0(%esp)
7379    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7380    UNSPILL(rPC)
7381    testl    %eax,%eax
7382    jne      .LOP_SGET_finish                 # success, continue
7383    jmp      common_exceptionThrown             # no, handle exception
7384
7385/* continuation for OP_SGET_WIDE */
7386
7387    /*
7388     * Go resolve the field
7389     */
7390.LOP_SGET_WIDE_resolve:
7391    GET_GLUE(%ecx)
7392    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7393    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7394    EXPORT_PC()                                 # could throw, need to export
7395    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7396    SPILL(rPC)
7397    movl     %eax,OUT_ARG1(%esp)
7398    movl     %ecx,OUT_ARG0(%esp)
7399    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7400    UNSPILL(rPC)
7401    testl    %eax,%eax
7402    jne      .LOP_SGET_WIDE_finish                 # success, continue
7403    jmp      common_exceptionThrown             # no, handle exception
7404
7405/* continuation for OP_SGET_OBJECT */
7406
7407    /*
7408     * Go resolve the field
7409     */
7410.LOP_SGET_OBJECT_resolve:
7411    GET_GLUE(%ecx)
7412    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7413    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7414    EXPORT_PC()                                 # could throw, need to export
7415    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7416    SPILL(rPC)
7417    movl     %eax,OUT_ARG1(%esp)
7418    movl     %ecx,OUT_ARG0(%esp)
7419    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7420    UNSPILL(rPC)
7421    testl    %eax,%eax
7422    jne      .LOP_SGET_OBJECT_finish                 # success, continue
7423    jmp      common_exceptionThrown             # no, handle exception
7424
7425/* continuation for OP_SGET_BOOLEAN */
7426
7427    /*
7428     * Go resolve the field
7429     */
7430.LOP_SGET_BOOLEAN_resolve:
7431    GET_GLUE(%ecx)
7432    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7433    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7434    EXPORT_PC()                                 # could throw, need to export
7435    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7436    SPILL(rPC)
7437    movl     %eax,OUT_ARG1(%esp)
7438    movl     %ecx,OUT_ARG0(%esp)
7439    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7440    UNSPILL(rPC)
7441    testl    %eax,%eax
7442    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
7443    jmp      common_exceptionThrown             # no, handle exception
7444
7445/* continuation for OP_SGET_BYTE */
7446
7447    /*
7448     * Go resolve the field
7449     */
7450.LOP_SGET_BYTE_resolve:
7451    GET_GLUE(%ecx)
7452    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7453    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7454    EXPORT_PC()                                 # could throw, need to export
7455    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7456    SPILL(rPC)
7457    movl     %eax,OUT_ARG1(%esp)
7458    movl     %ecx,OUT_ARG0(%esp)
7459    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7460    UNSPILL(rPC)
7461    testl    %eax,%eax
7462    jne      .LOP_SGET_BYTE_finish                 # success, continue
7463    jmp      common_exceptionThrown             # no, handle exception
7464
7465/* continuation for OP_SGET_CHAR */
7466
7467    /*
7468     * Go resolve the field
7469     */
7470.LOP_SGET_CHAR_resolve:
7471    GET_GLUE(%ecx)
7472    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7473    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7474    EXPORT_PC()                                 # could throw, need to export
7475    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7476    SPILL(rPC)
7477    movl     %eax,OUT_ARG1(%esp)
7478    movl     %ecx,OUT_ARG0(%esp)
7479    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7480    UNSPILL(rPC)
7481    testl    %eax,%eax
7482    jne      .LOP_SGET_CHAR_finish                 # success, continue
7483    jmp      common_exceptionThrown             # no, handle exception
7484
7485/* continuation for OP_SGET_SHORT */
7486
7487    /*
7488     * Go resolve the field
7489     */
7490.LOP_SGET_SHORT_resolve:
7491    GET_GLUE(%ecx)
7492    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7493    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7494    EXPORT_PC()                                 # could throw, need to export
7495    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7496    SPILL(rPC)
7497    movl     %eax,OUT_ARG1(%esp)
7498    movl     %ecx,OUT_ARG0(%esp)
7499    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7500    UNSPILL(rPC)
7501    testl    %eax,%eax
7502    jne      .LOP_SGET_SHORT_finish                 # success, continue
7503    jmp      common_exceptionThrown             # no, handle exception
7504
7505/* continuation for OP_SPUT */
7506
7507    /*
7508     * Go resolve the field
7509     */
7510.LOP_SPUT_resolve:
7511    GET_GLUE(%ecx)
7512    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7513    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7514    EXPORT_PC()                                 # could throw, need to export
7515    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7516    SPILL(rPC)
7517    movl     %eax,OUT_ARG1(%esp)
7518    movl     %ecx,OUT_ARG0(%esp)
7519    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7520    UNSPILL(rPC)
7521    testl    %eax,%eax
7522    jne      .LOP_SPUT_finish                 # success, continue
7523    jmp      common_exceptionThrown             # no, handle exception
7524
7525/* continuation for OP_SPUT_WIDE */
7526
7527    /*
7528     * Go resolve the field
7529     */
7530.LOP_SPUT_WIDE_resolve:
7531    GET_GLUE(%ecx)
7532    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7533    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7534    EXPORT_PC()                                 # could throw, need to export
7535    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7536    SPILL(rPC)
7537    movl     %eax,OUT_ARG1(%esp)
7538    movl     %ecx,OUT_ARG0(%esp)
7539    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7540    UNSPILL(rPC)
7541    testl    %eax,%eax
7542    jne      .LOP_SPUT_WIDE_finish                 # success, continue
7543    jmp      common_exceptionThrown             # no, handle exception
7544
7545/* continuation for OP_SPUT_OBJECT */
7546
7547    /*
7548     * Go resolve the field
7549     */
7550.LOP_SPUT_OBJECT_resolve:
7551    GET_GLUE(%ecx)
7552    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7553    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7554    EXPORT_PC()                                 # could throw, need to export
7555    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7556    SPILL(rPC)
7557    movl     %eax,OUT_ARG1(%esp)
7558    movl     %ecx,OUT_ARG0(%esp)
7559    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7560    UNSPILL(rPC)
7561    testl    %eax,%eax
7562    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
7563    jmp      common_exceptionThrown             # no, handle exception
7564
7565/* continuation for OP_SPUT_BOOLEAN */
7566
7567    /*
7568     * Go resolve the field
7569     */
7570.LOP_SPUT_BOOLEAN_resolve:
7571    GET_GLUE(%ecx)
7572    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7573    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7574    EXPORT_PC()                                 # could throw, need to export
7575    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7576    SPILL(rPC)
7577    movl     %eax,OUT_ARG1(%esp)
7578    movl     %ecx,OUT_ARG0(%esp)
7579    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7580    UNSPILL(rPC)
7581    testl    %eax,%eax
7582    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
7583    jmp      common_exceptionThrown             # no, handle exception
7584
7585/* continuation for OP_SPUT_BYTE */
7586
7587    /*
7588     * Go resolve the field
7589     */
7590.LOP_SPUT_BYTE_resolve:
7591    GET_GLUE(%ecx)
7592    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7593    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7594    EXPORT_PC()                                 # could throw, need to export
7595    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7596    SPILL(rPC)
7597    movl     %eax,OUT_ARG1(%esp)
7598    movl     %ecx,OUT_ARG0(%esp)
7599    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7600    UNSPILL(rPC)
7601    testl    %eax,%eax
7602    jne      .LOP_SPUT_BYTE_finish                 # success, continue
7603    jmp      common_exceptionThrown             # no, handle exception
7604
7605/* continuation for OP_SPUT_CHAR */
7606
7607    /*
7608     * Go resolve the field
7609     */
7610.LOP_SPUT_CHAR_resolve:
7611    GET_GLUE(%ecx)
7612    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7613    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7614    EXPORT_PC()                                 # could throw, need to export
7615    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7616    SPILL(rPC)
7617    movl     %eax,OUT_ARG1(%esp)
7618    movl     %ecx,OUT_ARG0(%esp)
7619    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7620    UNSPILL(rPC)
7621    testl    %eax,%eax
7622    jne      .LOP_SPUT_CHAR_finish                 # success, continue
7623    jmp      common_exceptionThrown             # no, handle exception
7624
7625/* continuation for OP_SPUT_SHORT */
7626
7627    /*
7628     * Go resolve the field
7629     */
7630.LOP_SPUT_SHORT_resolve:
7631    GET_GLUE(%ecx)
7632    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
7633    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
7634    EXPORT_PC()                                 # could throw, need to export
7635    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
7636    SPILL(rPC)
7637    movl     %eax,OUT_ARG1(%esp)
7638    movl     %ecx,OUT_ARG0(%esp)
7639    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
7640    UNSPILL(rPC)
7641    testl    %eax,%eax
7642    jne      .LOP_SPUT_SHORT_finish                 # success, continue
7643    jmp      common_exceptionThrown             # no, handle exception
7644
7645/* continuation for OP_INVOKE_VIRTUAL */
7646
7647
7648.LOP_INVOKE_VIRTUAL_more:
7649    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7650    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7651    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7652    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7653    UNSPILL(rPC)
7654    testl     %eax,%eax                   # got null?
7655    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
7656    jmp       common_exceptionThrown      # yes, handle exception
7657
7658    /* At this point:
7659     *   eax = resolved base method
7660     *   ecx = scratch
7661     */
7662.LOP_INVOKE_VIRTUAL_continue:
7663    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7664    .if       (!0)
7665    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7666    .endif
7667    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7668    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7669    testl     %ecx,%ecx                 # null this?
7670    je        common_errNullObject      # go if so
7671    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7672    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7673    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7674    jmp       common_invokeMethodNoRange
7675
7676/* continuation for OP_INVOKE_SUPER */
7677
7678    /*
7679     * At this point:
7680     *  ecx = resolved base method [r0]
7681     *  eax = method->clazz [r9]
7682     */
7683.LOP_INVOKE_SUPER_continue:
7684    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7685    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7686    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7687    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
7688    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7689    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7690    jmp     common_invokeMethodNoRange
7691
7692
7693    /* At this point:
7694     * ecx = null (needs to be resolved base method)
7695     * eax = method->clazz
7696    */
7697.LOP_INVOKE_SUPER_resolve:
7698    SPILL_TMP(%eax)                     # method->clazz
7699    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7700    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7701    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7702    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7703    SPILL(rPC)
7704    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7705    UNSPILL(rPC)
7706    testl   %eax,%eax                   # got null?
7707    movl    %eax,%ecx                   # ecx<- resolved base method
7708    UNSPILL_TMP(%eax)                   # restore method->clazz
7709    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
7710    jmp     common_exceptionThrown      # handle exception
7711
7712    /*
7713     * Throw a NoSuchMethodError with the method name as the message.
7714     *  ecx = resolved base method
7715     */
7716.LOP_INVOKE_SUPER_nsm:
7717    movl    offMethod_name(%ecx),%eax
7718    mov     %eax,OUT_ARG1(%esp)
7719    jmp     common_errNoSuchMethod
7720
7721/* continuation for OP_INVOKE_DIRECT */
7722
7723    /*
7724     * On entry:
7725     *   TMP_SPILL  <- "this" register
7726     * Things a bit ugly on this path, but it's the less
7727     * frequent one.  We'll have to do some reloading.
7728     */
7729.LOP_INVOKE_DIRECT_resolve:
7730     SPILL_TMP(%ecx)
7731     GET_GLUE(%ecx)
7732     UNSPILL(rPC)
7733     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7734     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7735     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7736     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7737     movl     %eax,OUT_ARG1(%esp)
7738     movl     %ecx,OUT_ARG0(%esp)
7739     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7740     UNSPILL_TMP(%ecx)
7741     testl    %eax,%eax
7742     jne      .LOP_INVOKE_DIRECT_finish
7743     UNSPILL(rPC)
7744     jmp      common_exceptionThrown
7745
7746/* continuation for OP_INVOKE_STATIC */
7747
7748.LOP_INVOKE_STATIC_continue:
7749    movl      $METHOD_STATIC,%eax
7750    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7751    SPILL(rPC)
7752    call      dvmResolveMethod          # call(clazz,ref,flags)
7753    UNSPILL(rPC)
7754    testl     %eax,%eax                 # got null?
7755    jne       common_invokeMethodNoRange
7756    jmp       common_exceptionThrown
7757
7758/* continuation for OP_INVOKE_INTERFACE */
7759
7760.LOP_INVOKE_INTERFACE_continue:
7761    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7762    UNSPILL(rPC)
7763    testl      %eax,%eax
7764    je         common_exceptionThrown
7765    jmp        common_invokeMethodNoRange
7766
7767/* continuation for OP_INVOKE_VIRTUAL_RANGE */
7768
7769
7770.LOP_INVOKE_VIRTUAL_RANGE_more:
7771    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
7772    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
7773    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
7774    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
7775    UNSPILL(rPC)
7776    testl     %eax,%eax                   # got null?
7777    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
7778    jmp       common_exceptionThrown      # yes, handle exception
7779
7780    /* At this point:
7781     *   eax = resolved base method
7782     *   ecx = scratch
7783     */
7784.LOP_INVOKE_VIRTUAL_RANGE_continue:
7785    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
7786    .if       (!1)
7787    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
7788    .endif
7789    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
7790    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
7791    testl     %ecx,%ecx                 # null this?
7792    je        common_errNullObject      # go if so
7793    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
7794    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
7795    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
7796    jmp       common_invokeMethodRange
7797
7798/* continuation for OP_INVOKE_SUPER_RANGE */
7799
7800    /*
7801     * At this point:
7802     *  ecx = resolved base method [r0]
7803     *  eax = method->clazz [r9]
7804     */
7805.LOP_INVOKE_SUPER_RANGE_continue:
7806    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
7807    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
7808    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
7809    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
7810    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
7811    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
7812    jmp     common_invokeMethodRange
7813
7814
7815    /* At this point:
7816     * ecx = null (needs to be resolved base method)
7817     * eax = method->clazz
7818    */
7819.LOP_INVOKE_SUPER_RANGE_resolve:
7820    SPILL_TMP(%eax)                     # method->clazz
7821    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
7822    movzwl  2(rPC),%ecx                 # ecx<- BBBB
7823    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
7824    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
7825    SPILL(rPC)
7826    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
7827    UNSPILL(rPC)
7828    testl   %eax,%eax                   # got null?
7829    movl    %eax,%ecx                   # ecx<- resolved base method
7830    UNSPILL_TMP(%eax)                   # restore method->clazz
7831    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
7832    jmp     common_exceptionThrown      # handle exception
7833
7834    /*
7835     * Throw a NoSuchMethodError with the method name as the message.
7836     *  ecx = resolved base method
7837     */
7838.LOP_INVOKE_SUPER_RANGE_nsm:
7839    movl    offMethod_name(%ecx),%eax
7840    mov     %eax,OUT_ARG1(%esp)
7841    jmp     common_errNoSuchMethod
7842
7843/* continuation for OP_INVOKE_DIRECT_RANGE */
7844
7845    /*
7846     * On entry:
7847     *   TMP_SPILL  <- "this" register
7848     * Things a bit ugly on this path, but it's the less
7849     * frequent one.  We'll have to do some reloading.
7850     */
7851.LOP_INVOKE_DIRECT_RANGE_resolve:
7852     SPILL_TMP(%ecx)
7853     GET_GLUE(%ecx)
7854     UNSPILL(rPC)
7855     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
7856     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
7857     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
7858     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
7859     movl     %eax,OUT_ARG1(%esp)
7860     movl     %ecx,OUT_ARG0(%esp)
7861     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
7862     UNSPILL_TMP(%ecx)
7863     testl    %eax,%eax
7864     jne      .LOP_INVOKE_DIRECT_RANGE_finish
7865     UNSPILL(rPC)
7866     jmp      common_exceptionThrown
7867
7868/* continuation for OP_INVOKE_STATIC_RANGE */
7869
7870.LOP_INVOKE_STATIC_RANGE_continue:
7871    movl      $METHOD_STATIC,%eax
7872    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
7873    SPILL(rPC)
7874    call      dvmResolveMethod          # call(clazz,ref,flags)
7875    UNSPILL(rPC)
7876    testl     %eax,%eax                 # got null?
7877    jne       common_invokeMethodRange
7878    jmp       common_exceptionThrown
7879
7880/* continuation for OP_INVOKE_INTERFACE_RANGE */
7881
7882.LOP_INVOKE_INTERFACE_RANGE_continue:
7883    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
7884    UNSPILL(rPC)
7885    testl      %eax,%eax
7886    je         common_exceptionThrown
7887    jmp        common_invokeMethodRange
7888
7889/* continuation for OP_FLOAT_TO_INT */
7890
7891
7892.LOP_FLOAT_TO_INT_continue:
7893    .if 0
7894    movl     $0x80000000,%eax
7895    xorl     4(rFP,%ecx,4),%eax
7896    orl      (rFP,%ecx,4),%eax
7897    .else
7898    cmpl     $0x80000000,(rFP,%ecx,4)
7899    .endif
7900    je       .LOP_FLOAT_TO_INT_special_case # fix up result
7901
7902.LOP_FLOAT_TO_INT_finish:
7903    ADVANCE_PC(1)
7904    GOTO_NEXT
7905
7906.LOP_FLOAT_TO_INT_special_case:
7907    fnstsw   %ax
7908    sahf
7909    jp       .LOP_FLOAT_TO_INT_isNaN
7910    adcl     $-1,(rFP,%ecx,4)
7911    .if 0
7912    adcl     $-1,4(rFP,%ecx,4)
7913    .endif
7914   jmp       .LOP_FLOAT_TO_INT_finish
7915.LOP_FLOAT_TO_INT_isNaN:
7916    movl      $0,(rFP,%ecx,4)
7917    .if 0
7918    movl      $0,4(rFP,%ecx,4)
7919    .endif
7920    jmp       .LOP_FLOAT_TO_INT_finish
7921
7922/* continuation for OP_FLOAT_TO_LONG */
7923
7924
7925.LOP_FLOAT_TO_LONG_continue:
7926    .if 1
7927    movl     $0x80000000,%eax
7928    xorl     4(rFP,%ecx,4),%eax
7929    orl      (rFP,%ecx,4),%eax
7930    .else
7931    cmpl     $0x80000000,(rFP,%ecx,4)
7932    .endif
7933    je       .LOP_FLOAT_TO_LONG_special_case # fix up result
7934
7935.LOP_FLOAT_TO_LONG_finish:
7936    ADVANCE_PC(1)
7937    GOTO_NEXT
7938
7939.LOP_FLOAT_TO_LONG_special_case:
7940    fnstsw   %ax
7941    sahf
7942    jp       .LOP_FLOAT_TO_LONG_isNaN
7943    adcl     $-1,(rFP,%ecx,4)
7944    .if 1
7945    adcl     $-1,4(rFP,%ecx,4)
7946    .endif
7947   jmp       .LOP_FLOAT_TO_LONG_finish
7948.LOP_FLOAT_TO_LONG_isNaN:
7949    movl      $0,(rFP,%ecx,4)
7950    .if 1
7951    movl      $0,4(rFP,%ecx,4)
7952    .endif
7953    jmp       .LOP_FLOAT_TO_LONG_finish
7954
7955/* continuation for OP_DOUBLE_TO_INT */
7956
7957
7958.LOP_DOUBLE_TO_INT_continue:
7959    .if 0
7960    movl     $0x80000000,%eax
7961    xorl     4(rFP,%ecx,4),%eax
7962    orl      (rFP,%ecx,4),%eax
7963    .else
7964    cmpl     $0x80000000,(rFP,%ecx,4)
7965    .endif
7966    je       .LOP_DOUBLE_TO_INT_special_case # fix up result
7967
7968.LOP_DOUBLE_TO_INT_finish:
7969    ADVANCE_PC(1)
7970    GOTO_NEXT
7971
7972.LOP_DOUBLE_TO_INT_special_case:
7973    fnstsw   %ax
7974    sahf
7975    jp       .LOP_DOUBLE_TO_INT_isNaN
7976    adcl     $-1,(rFP,%ecx,4)
7977    .if 0
7978    adcl     $-1,4(rFP,%ecx,4)
7979    .endif
7980   jmp       .LOP_DOUBLE_TO_INT_finish
7981.LOP_DOUBLE_TO_INT_isNaN:
7982    movl      $0,(rFP,%ecx,4)
7983    .if 0
7984    movl      $0,4(rFP,%ecx,4)
7985    .endif
7986    jmp       .LOP_DOUBLE_TO_INT_finish
7987
7988/* continuation for OP_DOUBLE_TO_LONG */
7989
7990
7991.LOP_DOUBLE_TO_LONG_continue:
7992    .if 1
7993    movl     $0x80000000,%eax
7994    xorl     4(rFP,%ecx,4),%eax
7995    orl      (rFP,%ecx,4),%eax
7996    .else
7997    cmpl     $0x80000000,(rFP,%ecx,4)
7998    .endif
7999    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result
8000
8001.LOP_DOUBLE_TO_LONG_finish:
8002    ADVANCE_PC(1)
8003    GOTO_NEXT
8004
8005.LOP_DOUBLE_TO_LONG_special_case:
8006    fnstsw   %ax
8007    sahf
8008    jp       .LOP_DOUBLE_TO_LONG_isNaN
8009    adcl     $-1,(rFP,%ecx,4)
8010    .if 1
8011    adcl     $-1,4(rFP,%ecx,4)
8012    .endif
8013   jmp       .LOP_DOUBLE_TO_LONG_finish
8014.LOP_DOUBLE_TO_LONG_isNaN:
8015    movl      $0,(rFP,%ecx,4)
8016    .if 1
8017    movl      $0,4(rFP,%ecx,4)
8018    .endif
8019    jmp       .LOP_DOUBLE_TO_LONG_finish
8020
8021/* continuation for OP_DIV_INT */
8022.LOP_DIV_INT_continue_div:
8023    cltd
8024    idivl   %ecx
8025.LOP_DIV_INT_finish_div:
8026    movzbl   rINST_HI,%ecx         # ecl<- AA
8027    SET_VREG(%eax,%ecx)
8028    UNSPILL(rPC)
8029    FETCH_INST_WORD(2)
8030    ADVANCE_PC(2)
8031    GOTO_NEXT
8032
8033/* continuation for OP_REM_INT */
8034.LOP_REM_INT_continue_div:
8035    cltd
8036    idivl   %ecx
8037.LOP_REM_INT_finish_div:
8038    movzbl   rINST_HI,%ecx         # ecl<- AA
8039    SET_VREG(%edx,%ecx)
8040    UNSPILL(rPC)
8041    FETCH_INST_WORD(2)
8042    ADVANCE_PC(2)
8043    GOTO_NEXT
8044
8045/* continuation for OP_MUL_LONG */
8046
8047.LOP_MUL_LONG_continue:
8048    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8049    movzbl    rINST_HI,%ecx       # ecx<- A
8050    movl      %edx,4(rFP,%ecx,4)  # v[B+1]<- %edx
8051    UNSPILL(rPC)                  # restore rPC/%edx
8052    FETCH_INST_WORD(2)
8053    UNSPILL(rIBASE)
8054    movl      %eax,(rFP,%ecx,4)   # v[B]<- %eax
8055    ADVANCE_PC(2)
8056    GOTO_NEXT
8057
8058/* continuation for OP_DIV_LONG */
8059
8060.LOP_DIV_LONG_continue:
8061    call     __divdi3
8062.LOP_DIV_LONG_finish:
8063    movzbl   rINST_HI,%ecx
8064    SET_VREG_WORD(rPC,%ecx,1)
8065    UNSPILL(rPC)
8066    SET_VREG_WORD(%eax,%ecx,0)
8067    FETCH_INST_WORD(2)
8068    ADVANCE_PC(2)
8069    GOTO_NEXT
8070
8071.LOP_DIV_LONG_check_zero:
8072    testl   rPC,rPC
8073    jne     .LOP_DIV_LONG_notSpecial
8074    UNSPILL(rPC)
8075    jmp     common_errDivideByZero
8076.LOP_DIV_LONG_check_neg1:
8077    testl   rPC,%eax
8078    jne     .LOP_DIV_LONG_notSpecial
8079    GET_VREG_WORD(rPC,%ecx,0)
8080    GET_VREG_WORD(%ecx,%ecx,1)
8081    testl    rPC,rPC
8082    jne      .LOP_DIV_LONG_notSpecial1
8083    cmpl     $0x80000000,%ecx
8084    jne      .LOP_DIV_LONG_notSpecial1
8085    /* minint / -1, return minint on div, 0 on rem */
8086    xorl     %eax,%eax
8087    movl     $0x80000000,%edx
8088    jmp      .LOP_DIV_LONG_finish
8089
8090/* continuation for OP_REM_LONG */
8091
8092.LOP_REM_LONG_continue:
8093    call     __moddi3
8094.LOP_REM_LONG_finish:
8095    movzbl   rINST_HI,%ecx
8096    SET_VREG_WORD(rPC,%ecx,1)
8097    UNSPILL(rPC)
8098    SET_VREG_WORD(%eax,%ecx,0)
8099    FETCH_INST_WORD(2)
8100    ADVANCE_PC(2)
8101    GOTO_NEXT
8102
8103.LOP_REM_LONG_check_zero:
8104    testl   rPC,rPC
8105    jne     .LOP_REM_LONG_notSpecial
8106    UNSPILL(rPC)
8107    jmp     common_errDivideByZero
8108.LOP_REM_LONG_check_neg1:
8109    testl   rPC,%eax
8110    jne     .LOP_REM_LONG_notSpecial
8111    GET_VREG_WORD(rPC,%ecx,0)
8112    GET_VREG_WORD(%ecx,%ecx,1)
8113    testl    rPC,rPC
8114    jne      .LOP_REM_LONG_notSpecial1
8115    cmpl     $0x80000000,%ecx
8116    jne      .LOP_REM_LONG_notSpecial1
8117    /* minint / -1, return minint on div, 0 on rem */
8118    xorl     %eax,%eax
8119    movl     $0,%edx
8120    jmp      .LOP_REM_LONG_finish
8121
8122/* continuation for OP_SHL_LONG */
8123
8124.LOP_SHL_LONG_finish:
8125    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- %eax
8126    ADVANCE_PC(2)
8127    GOTO_NEXT
8128
8129/* continuation for OP_SHR_LONG */
8130
8131
8132.LOP_SHR_LONG_finish:
8133    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- eax
8134    ADVANCE_PC(2)
8135    GOTO_NEXT
8136
8137/* continuation for OP_USHR_LONG */
8138
8139
8140.LOP_USHR_LONG_finish:
8141    SET_VREG_WORD(%eax,%ecx,0)        # v[BB+0]<- eax
8142    FETCH_INST_WORD(2)
8143    ADVANCE_PC(2)
8144    GOTO_NEXT
8145
8146/* continuation for OP_DIV_INT_2ADDR */
8147.LOP_DIV_INT_2ADDR_continue_div2addr:
8148    cltd
8149    idivl   %ecx
8150.LOP_DIV_INT_2ADDR_finish_div2addr:
8151    SET_VREG(%eax,rINST_FULL)
8152    UNSPILL(rPC)
8153    FETCH_INST_WORD(1)
8154    ADVANCE_PC(1)
8155    GOTO_NEXT
8156
8157/* continuation for OP_REM_INT_2ADDR */
8158.LOP_REM_INT_2ADDR_continue_div2addr:
8159    cltd
8160    idivl   %ecx
8161.LOP_REM_INT_2ADDR_finish_div2addr:
8162    SET_VREG(%edx,rINST_FULL)
8163    UNSPILL(rPC)
8164    FETCH_INST_WORD(1)
8165    ADVANCE_PC(1)
8166    GOTO_NEXT
8167
8168/* continuation for OP_MUL_LONG_2ADDR */
8169
8170.LOP_MUL_LONG_2ADDR_continue:
8171    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
8172    movl      %edx,4(rIBASE)      # v[A+1]<- %edx
8173    UNSPILL(rPC)                  # restore rPC/%edx
8174    FETCH_INST_WORD(1)
8175    movl      %eax,(rIBASE)       # v[A]<- %eax
8176    UNSPILL(rFP)
8177    UNSPILL(rIBASE)
8178    ADVANCE_PC(1)
8179    GOTO_NEXT
8180
8181/* continuation for OP_DIV_LONG_2ADDR */
8182
8183.LOP_DIV_LONG_2ADDR_continue:
8184    movl     %eax,OUT_ARG3(%esp)
8185    movl     rPC,OUT_ARG0(%esp)
8186    movl     %ecx,OUT_ARG1(%esp)
8187    call     __divdi3
8188.LOP_DIV_LONG_2ADDR_finish:
8189    movl     rINST_FULL,%ecx
8190    SET_VREG_WORD(rPC,%ecx,1)
8191    UNSPILL(rPC)
8192    SET_VREG_WORD(%eax,%ecx,0)
8193    FETCH_INST_WORD(1)
8194    ADVANCE_PC(1)
8195    GOTO_NEXT
8196
8197.LOP_DIV_LONG_2ADDR_check_zero:
8198    testl   rPC,rPC
8199    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8200    UNSPILL(rPC)
8201    jmp     common_errDivideByZero
8202.LOP_DIV_LONG_2ADDR_check_neg1:
8203    testl   rPC,%eax
8204    jne     .LOP_DIV_LONG_2ADDR_notSpecial
8205    GET_VREG_WORD(rPC,rINST_FULL,0)
8206    GET_VREG_WORD(%ecx,rINST_FULL,1)
8207    testl    rPC,rPC
8208    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8209    cmpl     $0x80000000,%ecx
8210    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
8211    /* minint / -1, return minint on div, 0 on rem */
8212    xorl     %eax,%eax
8213    movl     $0x80000000,%edx
8214    jmp      .LOP_DIV_LONG_2ADDR_finish
8215
8216/* continuation for OP_REM_LONG_2ADDR */
8217
8218.LOP_REM_LONG_2ADDR_continue:
8219    movl     %eax,OUT_ARG3(%esp)
8220    movl     rPC,OUT_ARG0(%esp)
8221    movl     %ecx,OUT_ARG1(%esp)
8222    call     __moddi3
8223.LOP_REM_LONG_2ADDR_finish:
8224    movl     rINST_FULL,%ecx
8225    SET_VREG_WORD(rPC,%ecx,1)
8226    UNSPILL(rPC)
8227    SET_VREG_WORD(%eax,%ecx,0)
8228    FETCH_INST_WORD(1)
8229    ADVANCE_PC(1)
8230    GOTO_NEXT
8231
8232.LOP_REM_LONG_2ADDR_check_zero:
8233    testl   rPC,rPC
8234    jne     .LOP_REM_LONG_2ADDR_notSpecial
8235    UNSPILL(rPC)
8236    jmp     common_errDivideByZero
8237.LOP_REM_LONG_2ADDR_check_neg1:
8238    testl   rPC,%eax
8239    jne     .LOP_REM_LONG_2ADDR_notSpecial
8240    GET_VREG_WORD(rPC,rINST_FULL,0)
8241    GET_VREG_WORD(%ecx,rINST_FULL,1)
8242    testl    rPC,rPC
8243    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8244    cmpl     $0x80000000,%ecx
8245    jne      .LOP_REM_LONG_2ADDR_notSpecial1
8246    /* minint / -1, return minint on div, 0 on rem */
8247    xorl     %eax,%eax
8248    movl     $0,%edx
8249    jmp      .LOP_REM_LONG_2ADDR_finish
8250
8251/* continuation for OP_SHL_LONG_2ADDR */
8252
8253
8254.LOP_SHL_LONG_2ADDR_finish:
8255    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8256    FETCH_INST_WORD(1)
8257    ADVANCE_PC(1)
8258    GOTO_NEXT
8259
8260/* continuation for OP_SHR_LONG_2ADDR */
8261
8262
8263.LOP_SHR_LONG_2ADDR_finish:
8264    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
8265    FETCH_INST_WORD(1)
8266    ADVANCE_PC(1)
8267    GOTO_NEXT
8268
8269/* continuation for OP_USHR_LONG_2ADDR */
8270
8271
8272.LOP_USHR_LONG_2ADDR_finish:
8273    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[AA+0]<- eax
8274    FETCH_INST_WORD(1)
8275    ADVANCE_PC(1)
8276    GOTO_NEXT
8277
8278/* continuation for OP_DIV_INT_LIT16 */
8279.LOP_DIV_INT_LIT16_continue_div:
8280    cltd
8281    idivl   %ecx
8282.LOP_DIV_INT_LIT16_finish_div:
8283    SET_VREG(%eax,rINST_FULL)
8284    UNSPILL(rPC)
8285    FETCH_INST_WORD(2)
8286    ADVANCE_PC(2)
8287    GOTO_NEXT
8288
8289/* continuation for OP_REM_INT_LIT16 */
8290.LOP_REM_INT_LIT16_continue_div:
8291    cltd
8292    idivl   %ecx
8293.LOP_REM_INT_LIT16_finish_div:
8294    SET_VREG(%edx,rINST_FULL)
8295    UNSPILL(rPC)
8296    FETCH_INST_WORD(2)
8297    ADVANCE_PC(2)
8298    GOTO_NEXT
8299
8300/* continuation for OP_DIV_INT_LIT8 */
8301.LOP_DIV_INT_LIT8_continue_div:
8302    cltd
8303    idivl   %ecx
8304.LOP_DIV_INT_LIT8_finish_div:
8305    SET_VREG(%eax,rINST_FULL)
8306    UNSPILL(rPC)
8307    FETCH_INST_WORD(2)
8308    ADVANCE_PC(2)
8309    GOTO_NEXT
8310
8311/* continuation for OP_REM_INT_LIT8 */
8312.LOP_REM_INT_LIT8_continue_div:
8313    cltd
8314    idivl   %ecx
8315.LOP_REM_INT_LIT8_finish_div:
8316    SET_VREG(%edx,rINST_FULL)
8317    UNSPILL(rPC)
8318    FETCH_INST_WORD(2)
8319    ADVANCE_PC(2)
8320    GOTO_NEXT
8321
8322/* continuation for OP_EXECUTE_INLINE */
8323
8324.LOP_EXECUTE_INLINE_continue:
8325    /*
8326     * Extract args, call function.
8327     *  ecx = #of args (0-4)
8328     *  eax = call index
8329     *  @esp = return addr
8330     *  esp is -4 from normal
8331     *
8332     *  Go ahead and load all 4 args, even if not used.
8333     */
8334    movzwl    4(rPC),rPC
8335
8336    movl      $0xf,%ecx
8337    andl      rPC,%ecx
8338    GET_VREG(%ecx,%ecx)
8339    sarl      $4,rPC
8340    movl      %ecx,4+OUT_ARG0(%esp)
8341
8342    movl      $0xf,%ecx
8343    andl      rPC,%ecx
8344    GET_VREG(%ecx,%ecx)
8345    sarl      $4,rPC
8346    movl      %ecx,4+OUT_ARG1(%esp)
8347
8348    movl      $0xf,%ecx
8349    andl      rPC,%ecx
8350    GET_VREG(%ecx,%ecx)
8351    sarl      $4,rPC
8352    movl      %ecx,4+OUT_ARG2(%esp)
8353
8354    movl      $0xf,%ecx
8355    andl      rPC,%ecx
8356    GET_VREG(%ecx,%ecx)
8357    sarl      $4,rPC
8358    movl      %ecx,4+OUT_ARG3(%esp)
8359
8360    sall      $4,%eax      # index *= sizeof(table entry)
8361    jmp       *gDvmInlineOpsTable(%eax)
8362    # will return to caller of .LOP_EXECUTE_INLINE_continue
8363
8364    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
8365    .global dvmAsmSisterEnd
8366dvmAsmSisterEnd:
8367
8368/* File: x86/entry.S */
8369/*
8370 * Copyright (C) 2008 The Android Open Source Project
8371 *
8372 * Licensed under the Apache License, Version 2.0 (the "License");
8373 * you may not use this file except in compliance with the License.
8374 * You may obtain a copy of the License at
8375 *
8376 *      http://www.apache.org/licenses/LICENSE-2.0
8377 *
8378 * Unless required by applicable law or agreed to in writing, software
8379 * distributed under the License is distributed on an "AS IS" BASIS,
8380 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8381 * See the License for the specific language governing permissions and
8382 * limitations under the License.
8383 */
8384
8385
8386    .text
8387    .global dvmMterpStdRun
8388    .type   dvmMterpStdRun, %function
8389/*
8390 * bool dvmMterpStdRun(MterpGlue* glue)
8391 *
8392 * Interpreter entry point.  Returns changeInterp.
8393 *
8394 */
8395dvmMterpStdRun:
8396    push    %ebp
8397    movl    %esp,%ebp
8398    push    %edi
8399    push    %esi
8400    push    %ebx
8401
8402/* at this point, stack is misaligned by 1 word
8403   We're allocating spill space for 6 words, plus
8404   outgoing argument (5 words) and local variables
8405   (4 words) - 15 words or 60 bytes total. See
8406   diagram in header.S
8407*/
8408    subl   $60,%esp
8409
8410/* Set up "named" registers */
8411    movl    IN_ARG0(%ebp),%ecx
8412    movl    %ecx,rGLUE_SPILL(%ebp)
8413    LOAD_PC_FROM_GLUE(%ecx)
8414    LOAD_FP_FROM_GLUE(%ecx)
8415    movl    $dvmAsmInstructionStart,rIBASE
8416
8417/* Remember %esp for future "longjmp" */
8418    movl    %esp,offGlue_bailPtr(%ecx)
8419
8420/* How to start? */
8421    movb    offGlue_entryPoint(%ecx),%al
8422
8423/* Normal start? */
8424    cmpb    $kInterpEntryInstr,%al
8425    jne     .Lnot_instr
8426
8427   /* Normal case: start executing the instruction at rPC */
8428    FETCH_INST()
8429    GOTO_NEXT
8430
8431.Lnot_instr:
8432    /* Reset to normal case */
8433    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8434    cmpb   $kInterpEntryReturn,%al
8435    je     common_returnFromMethod
8436    cmpb   $kInterpEntryThrow,%al
8437    je     common_exceptionThrown
8438    movzx  %al,%eax
8439    movl   %eax,OUT_ARG1(%esp)
8440    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
8441    call   printf
8442    call   dvmAbort
8443    /* Not reached */
8444
8445
8446    .global dvmMterpStdBail
8447    .type   dvmMterpStdBail, %function
8448/*
8449 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
8450 *
8451 * Restore the stack pointer and PC from the save point established on entry.
8452 * This is essentially the same as a longjmp, but should be cheaper.  The
8453 * last instruction causes us to return to whoever called dvmMterpStdRun.
8454 *
8455 * We're not going to build a standard frame here, so the arg accesses will
8456 * look a little strange.
8457 *
8458 * On entry:
8459 *  esp+4 (arg0)  MterpGlue* glue
8460 *  esp+8 (arg1)  bool changeInterp
8461 */
8462dvmMterpStdBail:
8463    movl    4(%esp),%ecx                 # grab glue
8464    movl    8(%esp),%eax                 # changeInterp to return reg
8465    movl    offGlue_bailPtr(%ecx),%esp   # Stack back to normal
8466    addl    $60,%esp                    # Strip dvmMterpStdRun's frame
8467    pop     %ebx
8468    pop     %esi
8469    pop     %edi
8470    pop     %ebp
8471    ret                                  # return to dvmMterpStdRun's caller
8472
8473
8474/*
8475 * Strings
8476 */
8477    .section    .rodata
8478.LstrBadEntryPoint:
8479    .asciz  "Bad entry point %d\n"
8480
8481/* File: x86/footer.S */
8482/*
8483 * Copyright (C) 2008 The Android Open Source Project
8484 *
8485 * Licensed under the Apache License, Version 2.0 (the "License");
8486 * you may not use this file except in compliance with the License.
8487 * You may obtain a copy of the License at
8488 *
8489 *      http://www.apache.org/licenses/LICENSE-2.0
8490 *
8491 * Unless required by applicable law or agreed to in writing, software
8492 * distributed under the License is distributed on an "AS IS" BASIS,
8493 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
8494 * See the License for the specific language governing permissions and
8495 * limitations under the License.
8496 */
8497/*
8498 * Common subroutines and data.
8499 */
8500
8501/*
8502 * Common code when a backwards branch is taken
8503 *
8504 * On entry:
8505 *   ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
8506 */
8507common_backwardBranch:
8508    GET_GLUE(%ecx)
8509    call   common_periodicChecks  # Note: expects rPC to be preserved
8510    ADVANCE_PC_INDEXED(rINST_FULL)
8511    FETCH_INST()
8512    GOTO_NEXT
8513
8514
8515
8516/*
8517 * Common code for method invocation with range.
8518 *
8519 * On entry:
8520 *   eax = Method* methodToCall
8521 *   rINST trashed, must reload
8522 */
8523
8524common_invokeMethodRange:
8525.LinvokeNewRange:
8526
8527   /*
8528    * prepare to copy args to "outs" area of current frame
8529    */
8530
8531    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
8532    movzwl      4(rPC), %ecx            # %ecx<- CCCC
8533    SPILL(rPC)
8534    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
8535    test        rINST_FULL, rINST_FULL
8536    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
8537    jz          .LinvokeArgsDone        # no args; jump to args done
8538
8539
8540   /*
8541    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
8542    * (very few methods have > 10 args; could unroll for common cases)
8543    */
8544
8545    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
8546    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
8547    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
8548    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
8549    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
85501:
8551    movl        (%ecx), %ebx            # %ebx<- vCCCC
8552    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
8553    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
8554    movl        %ebx, (%edx)            # *outs<- vCCCC
8555    lea         4(%edx), %edx           # outs++
8556    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
8557    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
8558    jmp         .LinvokeArgsDone        # continue
8559
8560   /*
8561    * %eax is "Method* methodToCall", the method we're trying to call
8562    * prepare to copy args to "outs" area of current frame
8563    */
8564
8565common_invokeMethodNoRange:
8566.LinvokeNewNoRange:
8567    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
8568    SPILL(rPC)
8569    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
8570    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
8571    je          .LinvokeArgsDone        # no args; jump to args done
8572    movzwl      4(rPC), %ecx            # %ecx<- GFED
8573    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
8574
8575   /*
8576    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
8577    */
8578
8579.LinvokeNonRange:
8580    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
8581    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
8582    jl          1f                      # handle 1 arg
8583    je          2f                      # handle 2 args
8584    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
8585    jl          3f                      # handle 3 args
8586    je          4f                      # handle 4 args
85875:
8588    andl        $15, rINST_FULL        # rINST<- A
8589    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
8590    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
8591    movl        %ecx, (%edx)            # *outs<- vA
8592    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
85934:
8594    shr         $12, %ecx              # %ecx<- G
8595    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
8596    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
8597    movl        %ecx, (%edx)            # *outs<- vG
8598    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
85993:
8600    and         $0x0f00, %ecx          # %ecx<- 0F00
8601    shr         $8, %ecx               # %ecx<- F
8602    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
8603    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
8604    movl        %ecx, (%edx)            # *outs<- vF
8605    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
86062:
8607    and         $0x00f0, %ecx          # %ecx<- 00E0
8608    shr         $4, %ecx               # %ecx<- E
8609    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
8610    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
8611    movl        %ecx, (%edx)            # *outs<- vE
8612    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
86131:
8614    and         $0x000f, %ecx          # %ecx<- 000D
8615    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
8616    movl        %ecx, -4(%edx)          # *--outs<- vD
86170:
8618
8619   /*
8620    * %eax is "Method* methodToCall", the method we're trying to call
8621    * find space for the new stack frame, check for overflow
8622    */
8623
8624.LinvokeArgsDone:
8625    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
8626    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
8627    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
8628    shl         $2, %edx               # %edx<- update offset
8629    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
8630    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
8631    GET_GLUE(%edx)                      # %edx<- pMterpGlue
8632    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
8633    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
8634    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
8635    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
8636    shl         $2, %ecx               # %ecx<- update offset for outsSize
8637    movl        %eax, %edx              # %edx<- newSaveArea
8638    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
8639    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
8640    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
8641    jl          .LstackOverflow         # handle frame overflow
8642
8643   /*
8644    * set up newSaveArea
8645    */
8646
8647#ifdef EASY_GDB
8648    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
8649    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
8650#endif
8651    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
8652    movl        rPC_SPILL(%ebp), %ecx
8653    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
8654    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
8655    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
8656    jne         .LinvokeNative          # handle native call
8657
8658   /*
8659    * Update "glue" values for the new method
8660    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
8661    */
8662
8663    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
8664    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
8665    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
8666    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
8667    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
8668    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
8669    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
8670    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
8671    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
8672    FETCH_INST()
8673    GOTO_NEXT                           # jump to methodToCall->insns
8674
8675   /*
8676    * Prep for the native call
8677    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
8678    */
8679
8680.LinvokeNative:
8681    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
8682    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
8683    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
8684    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
8685    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
8686    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
8687    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
8688    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
8689    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
8690    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
8691    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
8692    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
8693    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
8694    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
8695    push        %edx                    # push parameter newFP
8696
8697    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
8698    lea         4(%esp), %esp
8699    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
8700    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
8701    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
8702    cmp         $0, offThread_exception(%eax) # check for exception
8703    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
8704    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
8705    UNSPILL(rPC)
8706    jne         common_exceptionThrown  # handle exception
8707    FETCH_INST_WORD(3)
8708    ADVANCE_PC(3)
8709    GOTO_NEXT                           # jump to next instruction
8710
8711.LstackOverflow:    # eax=methodToCall
8712    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
8713    GET_GLUE(%eax)                      # %eax<- pMterpGlue
8714    movl        offGlue_self(%eax), %eax # %eax<- glue->self
8715    movl        %eax, OUT_ARG0(%esp)    # push parameter self
8716    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
8717    UNSPILL(rPC)                        # return: void
8718    jmp         common_exceptionThrown  # handle exception
8719
8720
8721/*
8722 * Common invoke code (old-style).
8723 * TUNING:  Rewrite along lines of new armv5 code?
8724 *
8725 * On entry:
8726 *   eax = Method* methodToCall
8727 *   ecx = bool methodCallRange
8728 *   rINST trashed, must reload
8729 */
8730common_invokeOld:
8731    movl     %ecx,OUT_ARG1(%esp)     # arg1<- methodCallRange
8732    GET_GLUE(%ecx)
8733    movzwl  (rPC),rINST_FULL         # recover rINST
8734    movl     %eax,OUT_ARG2(%esp)     # arg2<- method
8735    movzwl   4(rPC),%eax             # eax<- GFED or CCCC
8736    SAVE_PC_TO_GLUE(%ecx)
8737    SAVE_FP_TO_GLUE(%ecx)
8738    movzbl   rINST_HI,rINST_FULL
8739    movl     rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
8740    movl     %ecx,OUT_ARG0(%esp)     # arg0<- GLUE
8741    movl     %eax,OUT_ARG4(%esp)     # arg4<- GFED/CCCC
8742    call     dvmMterp_invokeMethod
8743    jmp      common_resumeAfterGlueCall
8744
8745
8746/*
8747 * Do we need the thread to be suspended or have debugger/profiling activity?
8748 *
8749 * On entry:
8750 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
8751 *   ecx  -> GLUE pointer
8752 *
8753 * Note: A call will normally kill %eax, rPC/%edx and %ecx.  To
8754 *       streamline the normal case, this routine will preserve rPC and
8755 *       %ecx in addition to the normal caller save regs.  The save/restore
8756 *       is a bit ugly, but will happen in the relatively uncommon path.
8757 * TUNING: Might be worthwhile to inline this.
8758 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
8759 *       the suspendCount check so we can get both in 1 shot.
8760 * TODO: to match the other intepreters, this should handle suspension
8761 *       and then check for debugger/profiling after dvmCheckSuspendPending
8762 *       returns.
8763 */
8764common_periodicChecks:
8765    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
8766    cmpl    $0,(%eax)
8767    jne     1f
8768
8769#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
8770#if defined(WITH_DEBUGGER)
8771    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
8772#endif
8773#if defined(WITH_PROFILER)
8774    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
8775#endif
8776#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
8777    # TODO: check for NULL before load
8778    movzbl (%eax),%eax             # eax <- debuggerActive (boolean)
8779    orl    (%ecx),%eax             # eax <- debuggerActive || activeProfilers
8780#elif defined(WITH_DEBUGGER)
8781    # TODO: check for NULL before load
8782    movzbl (%eax),%eax             # eax <- debuggerActive (boolean)
8783#elif defined(WITH_PROFILER)
8784    movl   (%ecx),%eax             # eax <= activeProfilers
8785#endif
8786    GET_GLUE(%ecx)                 # restore rGLUE
8787    testl  %eax,%eax
8788    jne    3f                      # one or both active - switch interp
8789#endif
8790
8791    ret
8792
8793    /* Check for suspend */
87941:
8795    /*  At this point, the return pointer to the caller of
8796     *  common_periodicChecks is on the top of stack.  We need to preserve
8797     *  rPC(edx) and GLUE(ecx).  We'll spill rPC, and reload GLUE.
8798     *  The outgoing profile is:
8799     *      bool dvmCheckSuspendPending(Thread* self)
8800     *  Because we reached here via a call, go ahead and build a new frame.
8801     */
8802    EXPORT_PC()                         # need for precise GC
8803    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
8804    SPILL(rPC)                      # save edx
8805    push    %ebp
8806    movl    %esp,%ebp
8807    subl    $24,%esp
8808    movl    %eax,OUT_ARG0(%esp)
8809    call    dvmCheckSuspendPending
8810    addl    $24,%esp
8811    pop     %ebp
8812    UNSPILL(rPC)
8813    GET_GLUE(%ecx)
8814    ret
8815
8816    /* Switch interpreters */
8817    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
8818     * "complete" the interpretation of backwards branches.  In effect, we
8819     * are completing the interpretation of the branch instruction here,
8820     * and the new interpreter will resume interpretation at the branch
8821     * target. However, a switch request recognized during the handling
8822     * of a return from method instruction results in an immediate abort,
8823     * and the new interpreter will resume by re-interpreting the return
8824     * instruction.
8825     */
88263:
8827    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
8828    GET_GLUE(%ecx)                 # bail expect GLUE already loaded
8829    movl    $1,rINST_FULL         # set changeInterp to true
8830    jmp     common_gotoBail
8831
8832
8833/*
8834 * Common code for handling a return instruction
8835 */
8836common_returnFromMethod:
8837    GET_GLUE(%ecx)
8838    /* Set entry mode in case we bail */
8839    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
8840    xorl    rINST_FULL,rINST_FULL   # zero offset in case we switch interps
8841    call    common_periodicChecks   # Note: expects %ecx to be preserved
8842
8843    SAVEAREA_FROM_FP(%eax,rFP)                    # eax<- saveArea (old)
8844    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
8845    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
8846    cmpl    $0,rINST_FULL                        # break?
8847    je      common_gotoBail    # break frame, bail out completely
8848
8849    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
8850    movl    offGlue_self(%ecx),%eax               # eax<- self
8851    movl    rINST_FULL,offGlue_method(%ecx)  # glue->method = newSave->meethod
8852    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
8853    movl    offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
8854    FETCH_INST_WORD(3)
8855    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
8856    ADVANCE_PC(3)
8857    movl    %eax,offGlue_methodClassDex(%ecx)
8858    /* not bailing - restore entry mode to default */
8859    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
8860    GOTO_NEXT
8861
8862/*
8863 * Prepare to strip the current frame and "longjump" back to caller of
8864 * dvmMterpStdRun.
8865 *
8866 * on entry:
8867 *    rINST_FULL holds changeInterp
8868 *    ecx holds glue pointer
8869 *
8870 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
8871 */
8872common_gotoBail:
8873    SAVE_PC_TO_GLUE(%ecx)                # export state to glue
8874    SAVE_FP_TO_GLUE(%ecx)
8875    movl   %ecx,OUT_ARG0(%esp)           # glue in arg0
8876    movl   rINST_FULL,OUT_ARG1(%esp)     # changeInterp in arg1
8877    call    dvmMterpStdBail              # bail out....
8878
8879
8880/*
8881 * After returning from a "glued" function, pull out the updated values
8882 * and start executing at the next instruction.
8883 */
8884 common_resumeAfterGlueCall:
8885     GET_GLUE(%ecx)
8886     LOAD_PC_FROM_GLUE(%ecx)
8887     LOAD_FP_FROM_GLUE(%ecx)
8888     FETCH_INST()
8889     GOTO_NEXT
8890
8891/*
8892 * Integer divide or mod by zero
8893 */
8894common_errDivideByZero:
8895    EXPORT_PC()
8896    movl    $.LstrArithmeticException,%eax
8897    movl    %eax,OUT_ARG0(%esp)
8898    movl    $.LstrDivideByZero,%eax
8899    movl    %eax,OUT_ARG1(%esp)
8900    SPILL(rPC)
8901    call    dvmThrowException
8902    UNSPILL(rPC)
8903    jmp     common_exceptionThrown
8904
8905/*
8906 * Attempt to allocate an array with a negative size.
8907 */
8908common_errNegativeArraySize:
8909    EXPORT_PC()
8910    movl    $.LstrNegativeArraySizeException,%eax
8911    movl    %eax,OUT_ARG0(%esp)
8912    xorl    %eax,%eax
8913    movl    %eax,OUT_ARG1(%esp)
8914    SPILL(rPC)
8915    call    dvmThrowException
8916    UNSPILL(rPC)
8917    jmp     common_exceptionThrown
8918
8919/*
8920 * Attempt to allocate an array with a negative size.
8921 */
8922common_errNoSuchMethod:
8923
8924    EXPORT_PC()
8925    movl    $.LstrNoSuchMethodError,%eax
8926    movl    %eax,OUT_ARG0(%esp)
8927    xorl    %eax,%eax
8928    movl    %eax,OUT_ARG1(%esp)
8929    SPILL(rPC)
8930    call    dvmThrowException
8931    UNSPILL(rPC)
8932    jmp     common_exceptionThrown
8933
8934/*
8935 * Hit a null object when we weren't expecting one.  Export the PC, throw a
8936 * NullPointerException and goto the exception processing code.
8937 */
8938common_errNullObject:
8939    EXPORT_PC()
8940    movl    $.LstrNullPointerException,%eax
8941    movl    %eax,OUT_ARG0(%esp)
8942    xorl    %eax,%eax
8943    movl    %eax,OUT_ARG1(%esp)
8944    SPILL(rPC)
8945    call    dvmThrowException
8946    UNSPILL(rPC)
8947    jmp     common_exceptionThrown
8948
8949/*
8950 * Array index exceeds max.
8951 */
8952common_errArrayIndex:
8953    EXPORT_PC()
8954    movl    $.LstrArrayIndexException,%eax
8955    movl    %eax,OUT_ARG0(%esp)
8956    xorl    %eax,%eax
8957    movl    %eax,OUT_ARG1(%esp)
8958    SPILL(rPC)
8959    call    dvmThrowException
8960    UNSPILL(rPC)
8961    jmp     common_exceptionThrown
8962/*
8963 * Invalid array value.
8964 */
8965common_errArrayStore:
8966    EXPORT_PC()
8967    movl    $.LstrArrayStoreException,%eax
8968    movl    %eax,OUT_ARG0(%esp)
8969    xorl    %eax,%eax
8970    movl    %eax,OUT_ARG1(%esp)
8971    SPILL(rPC)
8972    call    dvmThrowException
8973    UNSPILL(rPC)
8974    jmp     common_exceptionThrown
8975
8976/*
8977 * Somebody has thrown an exception.  Handle it.
8978 *
8979 * If the exception processing code returns to us (instead of falling
8980 * out of the interpreter), continue with whatever the next instruction
8981 * now happens to be.
8982 *
8983 * This does not return.
8984 */
8985common_exceptionThrown:
8986    GET_GLUE(%ecx)
8987    SAVE_PC_TO_GLUE(%ecx)
8988    SAVE_FP_TO_GLUE(%ecx)
8989    movl    %ecx,OUT_ARG0(%esp)
8990    call    dvmMterp_exceptionThrown
8991    jmp     common_resumeAfterGlueCall
8992
8993common_abort:
8994    movl    $0xdeadf00d,%eax
8995    call     *%eax
8996
8997
8998/*
8999 * Strings
9000 */
9001
9002    .section     .rodata
9003.LstrNullPointerException:
9004    .asciz    "Ljava/lang/NullPointerException;"
9005.LstrArithmeticException:
9006    .asciz  "Ljava/lang/ArithmeticException;"
9007.LstrDivideByZero:
9008    .asciz  "divide by zero"
9009.LstrArrayIndexException:
9010    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
9011.LstrArrayStoreException:
9012    .asciz  "Ljava/lang/ArrayStoreException;"
9013.LstrNegativeArraySizeException:
9014    .asciz  "Ljava/lang/NegativeArraySizeException;"
9015.LstrInstantiationError:
9016    .asciz  "Ljava/lang/InstantiationError;"
9017.LstrClassCastException:
9018    .asciz  "Ljava/lang/ClassCastException;"
9019.LstrNoSuchMethodError:
9020    .asciz  "Ljava/lang/NoSuchMethodError;"
9021.LstrInternalError:
9022    .asciz  "Ljava/lang/InternalError;"
9023.LstrFilledNewArrayNotImpl:
9024    .asciz  "filled-new-array only implemented for 'int'"
9025
9026