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