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