/*
 * This file was generated automatically by gen-mterp.py for 'x86'.
 *
 * --> DO NOT EDIT <--
 */

/* File: x86/header.S */
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * 32-bit x86 definitions and declarations.
 */

/*
386 ABI general notes:

Caller save set:
   eax, edx, ecx, st(0)-st(7)
Callee save set:
   ebx, esi, edi, ebp
Return regs:
   32-bit in eax
   64-bit in edx:eax (low-order 32 in eax)
   fp on top of fp stack st(0)

Parameters passed on stack, pushed right-to-left.  On entry to target, first
parm is at 4(%esp).  Traditional entry code is:

functEntry:
    push    %ebp             # save old frame pointer
    mov     %ebp,%esp        # establish new frame pointer
    sub     FrameSize,%esp   # Allocate storage for spill, locals & outs

Once past the prologue, arguments are referenced at ((argno + 2)*4)(%ebp)

Alignment of stack not strictly required, but should be for performance.  We'll
align frame sizes to 16-byte multiples.

If we're not doing variable stack allocation (alloca), the frame pointer can be
eliminated and all arg references adjusted to be esp relative.

Mterp notes:

Some key interpreter variables will be assigned to registers.  Note that each
will also have an associated spill location (mostly used useful for those assigned
to callee save registers).

  nick     reg   purpose
  rPC      edx   interpreted program counter, used for fetching instructions
  rFP      esi   interpreted frame pointer, used for accessing locals and args
  rIBASE   edi   Base pointer for instruction dispatch computed goto
  rINST    bx    first 16-bit code of current instruction
  rOPCODE  bl    opcode portion of instruction word
  rINST_HI bh    high byte of instruction word, usually contains src/tgt reg names

Notes:
   o High order 16 bits of ebx must be zero on entry to handler
   o rPC, rFP, rIBASE, rINST/rOPCODE valid on handler entry and exit
   o eax and ecx are scratch, rINST/ebx sometimes scratch
   o rPC is in the caller save set, and will be killed across external calls. Don't
     forget to SPILL/UNSPILL it around call points

*/

#define rPC      %edx
#define rFP      %esi
#define rIBASE   %edi
#define rINST_FULL %ebx
#define rINST    %bx
#define rINST_HI %bh
#define rINST_LO %bl
#define rOPCODE  %bl


/* Frame diagram while executing dvmMterpStdRun, high to low addresses */
#define IN_ARG0        (  8)
#define CALLER_RP      (  4)
#define PREV_FP        (  0) /* <- dvmMterpStdRun ebp */
/* Spill offsets relative to %ebp */
#define EDI_SPILL      ( -4)
#define ESI_SPILL      ( -8)
#define EDX_SPILL      (-12) /* <- esp following dmMterpStdRun header */
#define rPC_SPILL      (-16)
#define rFP_SPILL      (-20)
#define rGLUE_SPILL    (-24)
#define rIBASE_SPILL   (-28)
#define rINST_FULL_SPILL    (-32)
#define TMP_SPILL      (-36)
#define LOCAL0_OFFSET  (-40)
#define LOCAL1_OFFSET  (-44)
#define LOCAL2_OFFSET  (-48)
#define LOCAL3_OFFSET  (-52)
/* Out Arg offsets, relative to %sp */
#define OUT_ARG4       ( 16)
#define OUT_ARG3       ( 12)
#define OUT_ARG2       (  8)
#define OUT_ARG1       (  4)
#define OUT_ARG0       (  0)  /* <- dvmMterpStdRun esp */

#define SPILL(reg) movl reg##,reg##_SPILL(%ebp)
#define UNSPILL(reg) movl reg##_SPILL(%ebp),reg
#define SPILL_TMP(reg) movl reg,TMP_SPILL(%ebp)
#define UNSPILL_TMP(reg) movl TMP_SPILL(%ebp),reg


/* save/restore the PC and/or FP from the glue struct */
#define LOAD_PC_FROM_GLUE(_glu)     movl    offGlue_pc(_glu),rPC
#define SAVE_PC_TO_GLUE(_glu)       movl    rPC,offGlue_pc(_glu)
#define LOAD_FP_FROM_GLUE(_glu)     movl    offGlue_fp(_glu),rFP
#define SAVE_FP_TO_GLUE(_glu)       movl    rFP,offGlue_fp(_glu)

#define GET_GLUE(_reg)     movl   rGLUE_SPILL(%ebp),_reg

/* The interpreter assumes a properly aligned stack on entry, and
 * will preserve 16-byte alignment.
 */

/*
 * "export" the PC to the interpreted stack frame, f/b/o future exception
 * objects.  Must * be done *before* something calls dvmThrowException.
 *
 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
 *
 * It's okay to do this more than once.
 */
#define EXPORT_PC() \
    movl     rPC, (-sizeofStackSaveArea + offStackSaveArea_currentPc)(rFP)

/*
 * Given a frame pointer, find the stack save area.
 *
 * In C this is "((StackSaveArea*)(_fp) -1)".
 */
#define SAVEAREA_FROM_FP(_reg, _fpreg) \
    leal    -sizeofStackSaveArea(_fpreg),_reg

/*
 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
 */
#define FETCH_INST()            movzwl    (rPC),rINST_FULL

/*
 * Fetch the nth instruction word from rPC into rINST.  Does not advance
 * rPC, and _count is in words
 */
#define FETCH_INST_WORD(_count)  movzwl  _count*2(rPC),rINST_FULL

/*
 * Fetch instruction word indexed (used for branching).
 * Index is in instruction word units.
 */
#define FETCH_INST_INDEXED(_reg) movzwl  (rPC,_reg,2),rINST_FULL

/*
 * Extract the opcode of the instruction in rINST
 */
#define EXTRACT_OPCODE(_reg)   movzx rOPCODE,_reg

/*
 * Advance rPC by instruction count
 */
#define ADVANCE_PC(_count)    leal  2*_count(rPC),rPC

/*
 * Advance rPC by branch offset in register
 */
#define ADVANCE_PC_INDEXED(_reg) leal (rPC,_reg,2),rPC

/*
 * Note: assumes opcode previously fetched and in rINST, and
 *       %eax is killable at this point.
 */
#if 1
.macro GOTO_NEXT
    /* For computed next version */
     movzx    rOPCODE,%eax
     sall     $6,%eax
     addl     rIBASE,%eax
     jmp      *%eax
.endm
#else
   /* For jump table version */
.macro GOTO_NEXT
     movzx   rOPCODE,%eax
     jmp     *(rIBASE,%eax,4)
.endm
#endif

/*
 * Get/set the 32-bit value from a Dalvik register.
 */
#define GET_VREG(_reg, _vreg)   movl     (rFP,_vreg,4),_reg
#define SET_VREG(_reg, _vreg)   movl     _reg,(rFP,_vreg,4)
#define GET_VREG_WORD(_reg, _vreg, _offset)   movl     4*(_offset)(rFP,_vreg,4),_reg
#define SET_VREG_WORD(_reg, _vreg, _offset)   movl     _reg,4*(_offset)(rFP,_vreg,4)

/*
 * This is a #include, not a %include, because we want the C pre-processor
 * to expand the macros into assembler assignment statements.
 */
#include "../common/asm-constants.h"


    .global dvmAsmInstructionStart
    .type   dvmAsmInstructionStart, %function
dvmAsmInstructionStart = .L_OP_NOP
    .text

/* ------------------------------ */
    .balign 64
.L_OP_NOP: /* 0x00 */
/* File: x86/OP_NOP.S */
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE: /* 0x01 */
/* File: x86/OP_MOVE.S */
    /* for move, move-object, long-to-int */
    /* op vA, vB */
    movzbl rINST_HI,%eax         # eax<- BA
    andb   $0xf,%al             # eax<- A
    shrl   $12,rINST_FULL       # rINST_FULL<- B
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    SET_VREG(%ecx,%eax)          # fp[A]<-fp[B]
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_FROM16: /* 0x02 */
/* File: x86/OP_MOVE_FROM16.S */
    /* for: move/from16, move-object/from16 */
    /* op vAA, vBBBB */
    movzx    rINST_HI,%eax            # eax <= AA
    movw     2(rPC),rINST             # rINST <= BBBB
    GET_VREG (%ecx,rINST_FULL)        # ecx<- fp[BBBB]
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG (%ecx,%eax)              # fp[AA]<- ecx]
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_16: /* 0x03 */
/* File: x86/OP_MOVE_16.S */
    /* for: move/16, move-object/16 */
    /* op vAAAA, vBBBB */
    movzwl    4(rPC),%ecx              # ecx<- BBBB
    movzwl    2(rPC),%eax              # eax<- AAAA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    SET_VREG(%ecx,%eax)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_WIDE: /* 0x04 */
/* File: x86/OP_MOVE_WIDE.S */
    /* move-wide vA, vB */
    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    movzbl    rINST_HI,%ecx                # ecx <- BA
    sarl      $12,rINST_FULL              # rinst_FULL<- B
    GET_VREG_WORD(%eax,rINST_FULL,0)       # eax<- v[B+0]
    GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- v[B+1]
    andb      $0xf,%cl                    # ecx <- A
    SET_VREG_WORD(rINST_FULL,%ecx,1)       # v[A+1]<- rINST_FULL
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    SET_VREG_WORD(%eax,%ecx,0)             # v[A+0]<- eax
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
/* File: x86/OP_MOVE_WIDE_FROM16.S */
    /* move-wide/from16 vAA, vBBBB */
    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    movzwl    2(rPC),%ecx              # ecx<- BBBB
    movzbl    rINST_HI,%eax            # eax<- AAAA
    GET_VREG_WORD(rINST_FULL,%ecx,0)   # rINST_FULL<- v[BBBB+0]
    GET_VREG_WORD(%ecx,%ecx,1)         # ecx<- v[BBBB+1]
    SET_VREG_WORD(rINST_FULL,%eax,0)   # v[AAAA+0]<- rINST_FULL
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG_WORD(%ecx,%eax,1)         # v[AAAA+1]<- eax
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_WIDE_16: /* 0x06 */
/* File: x86/OP_MOVE_WIDE_16.S */
    /* move-wide/16 vAAAA, vBBBB */
    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    movzwl    4(rPC),%ecx            # ecx<- BBBB
    movzwl    2(rPC),%eax            # eax<- AAAA
    GET_VREG_WORD(rINST_FULL,%ecx,0) # rINST_WORD<- v[BBBB+0]
    GET_VREG_WORD(%ecx,%ecx,1)       # ecx<- v[BBBB+1]
    SET_VREG_WORD(rINST_FULL,%eax,0) # v[AAAA+0]<- rINST_FULL
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    SET_VREG_WORD(%ecx,%eax,1)       # v[AAAA+1]<- ecx
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_OBJECT: /* 0x07 */
/* File: x86/OP_MOVE_OBJECT.S */
/* File: x86/OP_MOVE.S */
    /* for move, move-object, long-to-int */
    /* op vA, vB */
    movzbl rINST_HI,%eax         # eax<- BA
    andb   $0xf,%al             # eax<- A
    shrl   $12,rINST_FULL       # rINST_FULL<- B
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    SET_VREG(%ecx,%eax)          # fp[A]<-fp[B]
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
/* File: x86/OP_MOVE_OBJECT_FROM16.S */
/* File: x86/OP_MOVE_FROM16.S */
    /* for: move/from16, move-object/from16 */
    /* op vAA, vBBBB */
    movzx    rINST_HI,%eax            # eax <= AA
    movw     2(rPC),rINST             # rINST <= BBBB
    GET_VREG (%ecx,rINST_FULL)        # ecx<- fp[BBBB]
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG (%ecx,%eax)              # fp[AA]<- ecx]
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MOVE_OBJECT_16: /* 0x09 */
/* File: x86/OP_MOVE_OBJECT_16.S */
/* File: x86/OP_MOVE_16.S */
    /* for: move/16, move-object/16 */
    /* op vAAAA, vBBBB */
    movzwl    4(rPC),%ecx              # ecx<- BBBB
    movzwl    2(rPC),%eax              # eax<- AAAA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    SET_VREG(%ecx,%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MOVE_RESULT: /* 0x0a */
/* File: x86/OP_MOVE_RESULT.S */
    /* for: move-result, move-result-object */
    /* op vAA */
    GET_GLUE(%eax)                         # eax<- rGLUE
    movzx    rINST_HI,%ecx                 # ecx<- AA
    movl     offGlue_retval(%eax),%eax     # eax<- glue->retval.l
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    SET_VREG (%eax,%ecx)                   # fp[AA]<- retval.l
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
/* File: x86/OP_MOVE_RESULT_WIDE.S */
    /* move-result-wide vAA */
    GET_GLUE(%ecx)
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    movl    offGlue_retval(%ecx),%eax
    movl    4+offGlue_retval(%ecx),%ecx
    SET_VREG_WORD(%eax,rINST_FULL,0)    # v[AA+0] <- eax
    SET_VREG_WORD(%ecx,rINST_FULL,1)    # v[AA+1] <- ecx
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
/* File: x86/OP_MOVE_RESULT_OBJECT.S */
/* File: x86/OP_MOVE_RESULT.S */
    /* for: move-result, move-result-object */
    /* op vAA */
    GET_GLUE(%eax)                         # eax<- rGLUE
    movzx    rINST_HI,%ecx                 # ecx<- AA
    movl     offGlue_retval(%eax),%eax     # eax<- glue->retval.l
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    SET_VREG (%eax,%ecx)                   # fp[AA]<- retval.l
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MOVE_EXCEPTION: /* 0x0d */
/* File: x86/OP_MOVE_EXCEPTION.S */
    /* move-exception vAA */
    GET_GLUE(%ecx)
    movzbl  rINST_HI,rINST_FULL        # rINST_FULL<- AA
    movl    offGlue_self(%ecx),%ecx    # ecx<- glue->self
    movl    offThread_exception(%ecx),%eax # eax<- dvmGetException bypass
    SET_VREG(%eax,rINST_FULL)          # fp[AA]<- exception object
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    movl    $0,offThread_exception(%ecx) # dvmClearException bypass
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_RETURN_VOID: /* 0x0e */
/* File: x86/OP_RETURN_VOID.S */
    jmp       common_returnFromMethod

/* ------------------------------ */
    .balign 64
.L_OP_RETURN: /* 0x0f */
/* File: x86/OP_RETURN.S */
    /*
     * Return a 32-bit value.  Copies the return value into the "glue"
     * structure, then jumps to the return handler.
     *
     * for: return, return-object
     */
    /* op vAA */
    GET_GLUE(%ecx)
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    GET_VREG(%eax,rINST_FULL)           # eax<- vAA
    movl    %eax,offGlue_retval(%ecx)   # retval.i <- AA
    jmp     common_returnFromMethod

/* ------------------------------ */
    .balign 64
.L_OP_RETURN_WIDE: /* 0x10 */
/* File: x86/OP_RETURN_WIDE.S */
    /*
     * Return a 64-bit value.  Copies the return value into the "glue"
     * structure, then jumps to the return handler.
     */
    /* return-wide vAA */
    GET_GLUE(%ecx)
    movzbl  rINST_HI,rINST_FULL            # rINST_FULL<- AA
    GET_VREG_WORD(%eax,rINST_FULL,0)       # eax<- v[AA+0]
    GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- v[AA+1]
    movl    %eax,offGlue_retval(%ecx)
    movl    rINST_FULL,4+offGlue_retval(%ecx)
    jmp     common_returnFromMethod

/* ------------------------------ */
    .balign 64
.L_OP_RETURN_OBJECT: /* 0x11 */
/* File: x86/OP_RETURN_OBJECT.S */
/* File: x86/OP_RETURN.S */
    /*
     * Return a 32-bit value.  Copies the return value into the "glue"
     * structure, then jumps to the return handler.
     *
     * for: return, return-object
     */
    /* op vAA */
    GET_GLUE(%ecx)
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    GET_VREG(%eax,rINST_FULL)           # eax<- vAA
    movl    %eax,offGlue_retval(%ecx)   # retval.i <- AA
    jmp     common_returnFromMethod


/* ------------------------------ */
    .balign 64
.L_OP_CONST_4: /* 0x12 */
/* File: x86/OP_CONST_4.S */
    /* const/4 vA, #+B */
    movsx   rINST_HI,%eax              # eax<-ssssssBx
    movl    $0xf,%ecx
    andl    %eax,%ecx                  # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    sarl    $4,%eax
    SET_VREG(%eax,%ecx)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_16: /* 0x13 */
/* File: x86/OP_CONST_16.S */
    /* const/16 vAA, #+BBBB */
    movswl  2(rPC),%ecx                # ecx<- ssssBBBB
    movzx   rINST_HI,%eax              # eax<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%ecx,%eax)                # vAA<- ssssBBBB
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST: /* 0x14 */
/* File: x86/OP_CONST.S */
    /* const vAA, #+BBBBbbbb */
    movzbl    rINST_HI,%ecx           # ecx<- AA
    movl      2(rPC),%eax               # grab all 32 bits at once
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    SET_VREG(%eax,%ecx)                 # vAA<- eax
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_HIGH16: /* 0x15 */
/* File: x86/OP_CONST_HIGH16.S */
    /* const/high16 vAA, #+BBBB0000 */
    movzwl     2(rPC),%eax                # eax<- 0000BBBB
    movzbl     rINST_HI,%ecx              # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    sall       $16,%eax                  # eax<- BBBB0000
    SET_VREG(%eax,%ecx)                   # vAA<- eax
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_WIDE_16: /* 0x16 */
/* File: x86/OP_CONST_WIDE_16.S */
    /* const-wide/16 vAA, #+BBBB */
    movswl    2(rPC),%eax               # eax<- ssssBBBB
    SPILL(rPC)
    movzbl    rINST_HI,%ecx             # ecx<- AA
    FETCH_INST_WORD(2)
    cltd                                # rPC:eax<- ssssssssssssBBBB
    SET_VREG_WORD(rPC,%ecx,1)           # store msw
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)          # store lsw
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_WIDE_32: /* 0x17 */
/* File: x86/OP_CONST_WIDE_32.S */
    /* const-wide/32 vAA, #+BBBBbbbb */
    movl     2(rPC),%eax               # eax<- BBBBbbbb
    SPILL(rPC)
    movzbl    rINST_HI,%ecx             # ecx<- AA
    FETCH_INST_WORD(3)
    cltd                                # rPC:eax<- ssssssssssssBBBB
    SET_VREG_WORD(rPC,%ecx,1)           # store msw
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)          # store lsw
    ADVANCE_PC(3)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_WIDE: /* 0x18 */
/* File: x86/OP_CONST_WIDE.S */
    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
    movl      2(rPC),%eax         # eax<- lsw
    movzbl    rINST_HI,%ecx       # ecx <- AA
    movl      6(rPC),rINST_FULL   # rINST_FULL<- msw
    leal      (rFP,%ecx,4),%ecx   # dst addr
    movl      rINST_FULL,4(%ecx)
    FETCH_INST_WORD(5)
    movl      %eax,(%ecx)
    ADVANCE_PC(5)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
/* File: x86/OP_CONST_WIDE_HIGH16.S */
    /* const-wide/high16 vAA, #+BBBB000000000000 */
    movzwl     2(rPC),%eax                # eax<- 0000BBBB
    movzbl     rINST_HI,%ecx              # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    sall       $16,%eax                  # eax<- BBBB0000
    SET_VREG_WORD(%eax,%ecx,1)            # v[AA+1]<- eax
    xorl       %eax,%eax
    SET_VREG_WORD(%eax,%ecx,0)            # v[AA+0]<- eax
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_STRING: /* 0x1a */
/* File: x86/OP_CONST_STRING.S */

    /* const/string vAA, String@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax              # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
    movzbl    rINST_HI,rINST_FULL      # rINST_FULL<- AA
    movl      offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
    movl      (%ecx,%eax,4),%eax       # eax<- rResString[BBBB]
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    testl     %eax,%eax                # resolved yet?
    je        .LOP_CONST_STRING_resolve
    SET_VREG(%eax,%ecx)                # vAA<- rResString[BBBB]
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_STRING_JUMBO: /* 0x1b */
/* File: x86/OP_CONST_STRING_JUMBO.S */

    /* const/string vAA, String@BBBBBBBB */
    GET_GLUE(%ecx)
    movl      2(rPC),%eax              # eax<- BBBBBBBB
    movl      offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
    movzbl    rINST_HI,rINST_FULL      # rINST_FULL<- AA
    movl      offDvmDex_pResStrings(%ecx),%ecx # ecx<- dvmDex->pResStrings
    movl      (%ecx,%eax,4),%eax       # eax<- rResString[BBBB]
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(3)
    testl     %eax,%eax                # resolved yet?
    je        .LOP_CONST_STRING_JUMBO_resolve
    SET_VREG(%eax,%ecx)                # vAA<- rResString[BBBB]
    ADVANCE_PC(3)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CONST_CLASS: /* 0x1c */
/* File: x86/OP_CONST_CLASS.S */

    /* const/class vAA, Class@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax              # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx# ecx<- glue->methodClassDex
    movzbl    rINST_HI,rINST_FULL      # rINST_FULL<- AA
    movl      offDvmDex_pResClasses(%ecx),%ecx # ecx<- dvmDex->pResClasses
    movl      (%ecx,%eax,4),%eax       # eax<- rResClasses[BBBB]
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    testl     %eax,%eax                # resolved yet?
    je        .LOP_CONST_CLASS_resolve
    SET_VREG(%eax,%ecx)                # vAA<- rResClasses[BBBB]
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_MONITOR_ENTER: /* 0x1d */
/* File: x86/OP_MONITOR_ENTER.S */
    /*
     * Synchronize on an object.
     */
    /* monitor-enter vAA */
    GET_GLUE(%ecx)
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    GET_VREG(%eax,rINST_FULL)           # eax<- vAA
    movl    offGlue_self(%ecx),%ecx     # ecx<- glue->self
    FETCH_INST_WORD(1)
    testl   %eax,%eax                   # null object?
    EXPORT_PC()                         # need for precise GC, MONITOR_TRACKING
    jne     .LOP_MONITOR_ENTER_continue
    jmp     common_errNullObject

/* ------------------------------ */
    .balign 64
.L_OP_MONITOR_EXIT: /* 0x1e */
/* File: x86/OP_MONITOR_EXIT.S */
    /*
     * Unlock an object.
     *
     * Exceptions that occur when unlocking a monitor need to appear as
     * if they happened at the following instruction.  See the Dalvik
     * instruction spec.
     */
    /* monitor-exit vAA */
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    GET_VREG(%eax,rINST_FULL)
    GET_GLUE(%ecx)
    EXPORT_PC()
    testl   %eax,%eax                   # null object?
    je      .LOP_MONITOR_EXIT_errNullObject   # go if so
    movl    offGlue_self(%ecx),%ecx     # ecx<- glue->self
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    movl    %ecx,OUT_ARG0(%esp)
    jmp     .LOP_MONITOR_EXIT_continue

/* ------------------------------ */
    .balign 64
.L_OP_CHECK_CAST: /* 0x1f */
/* File: x86/OP_CHECK_CAST.S */
    /*
     * Check to see if a cast from one class to another is allowed.
     */
    /* check-cast vAA, class@BBBB */
    GET_GLUE(%ecx)
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- vAA (object)
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
    testl     rINST_FULL,rINST_FULL     # is oject null?
    movl      offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
    je        .LOP_CHECK_CAST_okay          # null obj, cast always succeeds
    movl      (%ecx,%eax,4),%eax        # eax<- resolved class
    movl      offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
    testl     %eax,%eax                 # have we resolved this before?
    je        .LOP_CHECK_CAST_resolve       # no, go do it now
.LOP_CHECK_CAST_resolved:
    cmpl      %eax,%ecx                 # same class (trivial success)?
    jne       .LOP_CHECK_CAST_fullcheck     # no, do full check
.LOP_CHECK_CAST_okay:
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_INSTANCE_OF: /* 0x20 */
/* File: x86/OP_INSTANCE_OF.S */
    /*
     * Check to see if an object reference is an instance of a class.
     *
     * Most common situation is a non-null object, being compared against
     * an already-resolved class.
     */
    /* instance-of vA, vB, class@CCCC */
    movzbl  rINST_HI,%eax               # eax<- BA
    sarl    $4,%eax                    # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB (obj)
    GET_GLUE(%ecx)
    testl   %eax,%eax                   # object null?
    movl    offGlue_methodClassDex(%ecx),%ecx  # ecx<- pDvmDex
    SPILL(rPC)
    je      .LOP_INSTANCE_OF_store           # null obj, not instance, store it
    movzwl  2(rPC),rPC                  # rPC<- CCCC
    movl    offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
    movl    (%ecx,rPC,4),%ecx           # ecx<- resolved class
    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
    testl   %ecx,%ecx                   # have we resolved this before?
    je      .LOP_INSTANCE_OF_resolve         # not resolved, do it now
.LOP_INSTANCE_OF_resolved:  # eax<- obj->clazz, ecx<- resolved class
    cmpl    %eax,%ecx                   # same class (trivial success)?
    je      .LOP_INSTANCE_OF_trivial         # yes, trivial finish
    jmp     .LOP_INSTANCE_OF_fullcheck       # no, do full check

/* ------------------------------ */
    .balign 64
.L_OP_ARRAY_LENGTH: /* 0x21 */
/* File: x86/OP_ARRAY_LENGTH.S */
    /*
     * Return the length of an array.
     */
   movzbl   rINST_HI,%eax              # eax<- BA
   sarl     $12,rINST_FULL            # rINST_FULL<- B
   GET_VREG(%ecx,rINST_FULL)           # ecx<- vB (object ref)
   andb     $0xf,%al                  # eax<- A
   testl    %ecx,%ecx                  # is null?
   je       common_errNullObject
   FETCH_INST_WORD(1)
   movl     offArrayObject_length(%ecx),%ecx
   ADVANCE_PC(1)
   SET_VREG(%ecx,%eax)
   GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_NEW_INSTANCE: /* 0x22 */
/* File: x86/OP_NEW_INSTANCE.S */
    /*
     * Create a new instance of a class.
     */
    /* new-instance vAA, class@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- pDvmDex
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    movl      offDvmDex_pResClasses(%ecx),%ecx # ecx<- pDvmDex->pResClasses
    EXPORT_PC()
    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved class
    SPILL(rPC)
    testl     %ecx,%ecx                 # resolved?
    je        .LOP_NEW_INSTANCE_resolve       # no, go do it
.LOP_NEW_INSTANCE_resolved:  # on entry, ecx<- class
    cmpb      $CLASS_INITIALIZED,offClassObject_status(%ecx)
    je        .LOP_NEW_INSTANCE_initialized
    jmp       .LOP_NEW_INSTANCE_needinit

/* ------------------------------ */
    .balign 64
.L_OP_NEW_ARRAY: /* 0x23 */
/* File: x86/OP_NEW_ARRAY.S */
    /*
     * Allocate an array of objects, specified with the array class
     * and a count.
     *
     * The verifier guarantees that this is an array class, so we don't
     * check for it here.
     */
    /* new-array vA, vB, class@CCCC */
    GET_GLUE(%ecx)
    EXPORT_PC()
    movl    offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
    movzwl  2(rPC),%eax                       # eax<- CCCC
    movl    offDvmDex_pResClasses(%ecx),%ecx  # ecx<- pDvmDex->pResClasses
    movl    (%ecx,%eax,4),%ecx                # ecx<- resolved class
    movzbl  rINST_HI,%eax
    sarl    $4,%eax                          # eax<- B
    GET_VREG(%eax,%eax)                       # eax<- vB (array length)
    movzbl  rINST_HI,rINST_FULL
    andb    $0xf,rINST_LO                    # rINST_FULL<- A
    testl   %eax,%eax
    js      common_errNegativeArraySize       # bail
    testl   %ecx,%ecx                         # already resolved?
    jne     .LOP_NEW_ARRAY_finish                # yes, fast path
    jmp     .LOP_NEW_ARRAY_resolve               # resolve now

/* ------------------------------ */
    .balign 64
.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
/* File: x86/OP_FILLED_NEW_ARRAY.S */
    /*
     * Create a new array with elements filled from registers.
     *
     * for: filled-new-array, filled-new-array/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
    GET_GLUE(%eax)
    movzbl  rINST_HI,rINST_FULL               # rINST_FULL<- AA or BA
    movl    offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
    movzwl  2(rPC),%ecx                       # ecx<- BBBB
    movl    offDvmDex_pResClasses(%eax),%eax  # eax<- pDvmDex->pResClasses
    SPILL(rPC)
    movl    (%eax,%ecx,4),%eax                # eax<- resolved class
    EXPORT_PC()
    testl   %eax,%eax                         # already resolved?
    jne     .LOP_FILLED_NEW_ARRAY_continue              # yes, continue
    # less frequent path, so we'll redo some work
    GET_GLUE(%eax)
    movl    $0,OUT_ARG2(%esp)                # arg2<- false
    movl    %ecx,OUT_ARG1(%esp)               # arg1<- BBBB
    movl    offGlue_method(%eax),%eax         # eax<- glue->method
    jmp     .LOP_FILLED_NEW_ARRAY_more

/* ------------------------------ */
    .balign 64
.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
/* File: x86/OP_FILLED_NEW_ARRAY_RANGE.S */
/* File: x86/OP_FILLED_NEW_ARRAY.S */
    /*
     * Create a new array with elements filled from registers.
     *
     * for: filled-new-array, filled-new-array/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
    GET_GLUE(%eax)
    movzbl  rINST_HI,rINST_FULL               # rINST_FULL<- AA or BA
    movl    offGlue_methodClassDex(%eax),%eax # eax<- pDvmDex
    movzwl  2(rPC),%ecx                       # ecx<- BBBB
    movl    offDvmDex_pResClasses(%eax),%eax  # eax<- pDvmDex->pResClasses
    SPILL(rPC)
    movl    (%eax,%ecx,4),%eax                # eax<- resolved class
    EXPORT_PC()
    testl   %eax,%eax                         # already resolved?
    jne     .LOP_FILLED_NEW_ARRAY_RANGE_continue              # yes, continue
    # less frequent path, so we'll redo some work
    GET_GLUE(%eax)
    movl    $0,OUT_ARG2(%esp)                # arg2<- false
    movl    %ecx,OUT_ARG1(%esp)               # arg1<- BBBB
    movl    offGlue_method(%eax),%eax         # eax<- glue->method
    jmp     .LOP_FILLED_NEW_ARRAY_RANGE_more


/* ------------------------------ */
    .balign 64
.L_OP_FILL_ARRAY_DATA: /* 0x26 */
/* File: x86/OP_FILL_ARRAY_DATA.S */
    /* fill-array-data vAA, +BBBBBBBB */
    movl    2(rPC),%ecx                # ecx<- BBBBbbbb
    movzbl  rINST_HI,rINST_FULL        # rINST_FULL<- AA
    leal    (rPC,%ecx,2),%ecx          # ecx<- PC + BBBBbbbb*2
    GET_VREG(%eax,rINST_FULL)
    SPILL(rPC)
    EXPORT_PC()
    movl    %eax,OUT_ARG0(%esp)
    movl    %ecx,OUT_ARG1(%esp)
    call    dvmInterpHandleFillArrayData
    UNSPILL(rPC)
    FETCH_INST_WORD(3)
    testl   %eax,%eax                   # exception thrown?
    je      common_exceptionThrown
    ADVANCE_PC(3)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_THROW: /* 0x27 */
/* File: x86/OP_THROW.S */
    /*
     * Throw an exception object in the current thread.
     */
    /* throw vAA */
    GET_GLUE(%ecx)
    EXPORT_PC()
    movzbl   rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,rINST_FULL)          # eax<- exception object
    movl     offGlue_self(%ecx),%ecx   # ecx<- glue->self
    testl    %eax,%eax                 # null object?
    je       common_errNullObject
    movl     %eax,offThread_exception(%ecx) # thread->exception<- obj
    jmp      common_exceptionThrown

/* ------------------------------ */
    .balign 64
.L_OP_GOTO: /* 0x28 */
/* File: x86/OP_GOTO.S */
    /*
     * Unconditional branch, 8-bit offset.
     *
     * The branch distance is a signed code-unit offset, which we need to
     * double to get a byte offset.
     */
    /* goto +AA */
    movsbl  rINST_HI,rINST_FULL         # ebx<- ssssssAA
    testl   rINST_FULL,rINST_FULL       # test for <0
    js      common_backwardBranch
    movl    rINST_FULL,%eax
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_GOTO_16: /* 0x29 */
/* File: x86/OP_GOTO_16.S */
    /*
     * Unconditional branch, 16-bit offset.
     *
     * The branch distance is a signed code-unit offset
     */
    /* goto/16 +AAAA */
    movswl  2(rPC),rINST_FULL           # rINST_FULL<- ssssAAAA
    testl   rINST_FULL,rINST_FULL       # test for <0
    js      common_backwardBranch
    movl    rINST_FULL,%eax
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_GOTO_32: /* 0x2a */
/* File: x86/OP_GOTO_32.S */
    /*
     * Unconditional branch, 32-bit offset.
     *
     * The branch distance is a signed code-unit offset.
     *
     * Unlike most opcodes, this one is allowed to branch to itself, so
     * our "backward branch" test must be "<=0" instead of "<0".
     */
    /* goto/32 AAAAAAAA */
    movl    2(rPC),rINST_FULL           # rINST_FULL<- AAAAAAAA
    cmpl    $0,rINST_FULL              # test for <= 0
    jle     common_backwardBranch
    movl    rINST_FULL,%eax
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_PACKED_SWITCH: /* 0x2b */
/* File: x86/OP_PACKED_SWITCH.S */
    /*
     * Handle a packed-switch or sparse-switch instruction.  In both cases
     * we decode it and hand it off to a helper function.
     *
     * We don't really expect backward branches in a switch statement, but
     * they're perfectly legal, so we check for them here.
     *
     * for: packed-switch, sparse-switch
     */
    /* op vAA, +BBBB */
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    movl    2(rPC),%ecx                 # ecx<- BBBBbbbb
    GET_VREG(%eax,rINST_FULL)           # eax<- vAA
    leal    (rPC,%ecx,2),%ecx           # ecx<- PC + BBBBbbbb*2
    movl    %eax,OUT_ARG1(%esp)         # ARG1<- vAA
    movl    %ecx,OUT_ARG0(%esp)         # ARG0<- switchData
    SPILL(rPC)
    call    dvmInterpHandlePackedSwitch
    UNSPILL(rPC)
    testl   %eax,%eax
    movl    %eax,rINST_FULL             # set up word offset
    jle     common_backwardBranch       # check on special actions
    ADVANCE_PC_INDEXED(rINST_FULL)
    FETCH_INST()
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_SPARSE_SWITCH: /* 0x2c */
/* File: x86/OP_SPARSE_SWITCH.S */
/* File: x86/OP_PACKED_SWITCH.S */
    /*
     * Handle a packed-switch or sparse-switch instruction.  In both cases
     * we decode it and hand it off to a helper function.
     *
     * We don't really expect backward branches in a switch statement, but
     * they're perfectly legal, so we check for them here.
     *
     * for: packed-switch, sparse-switch
     */
    /* op vAA, +BBBB */
    movzbl  rINST_HI,rINST_FULL         # rINST_FULL<- AA
    movl    2(rPC),%ecx                 # ecx<- BBBBbbbb
    GET_VREG(%eax,rINST_FULL)           # eax<- vAA
    leal    (rPC,%ecx,2),%ecx           # ecx<- PC + BBBBbbbb*2
    movl    %eax,OUT_ARG1(%esp)         # ARG1<- vAA
    movl    %ecx,OUT_ARG0(%esp)         # ARG0<- switchData
    SPILL(rPC)
    call    dvmInterpHandleSparseSwitch
    UNSPILL(rPC)
    testl   %eax,%eax
    movl    %eax,rINST_FULL             # set up word offset
    jle     common_backwardBranch       # check on special actions
    ADVANCE_PC_INDEXED(rINST_FULL)
    FETCH_INST()
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_CMPL_FLOAT: /* 0x2d */
/* File: x86/OP_CMPL_FLOAT.S */
/* File: x86/OP_CMPG_DOUBLE.S */
    /* float/double_cmp[gl] vAA, vBB, vCC */
    movzbl    3(rPC),%eax             # eax<- CC
    movzbl    2(rPC),%ecx             # ecx<- BB
    .if 0
    fldl     (rFP,%eax,4)
    fldl     (rFP,%ecx,4)
    .else
    flds     (rFP,%eax,4)
    flds     (rFP,%ecx,4)
    .endif
    movzbl   rINST_HI,rINST_FULL
    xorl     %ecx,%ecx
    fucompp     # z if equal, p set if NaN, c set if st0 < st1
    fnstsw   %ax
    sahf
    movl      rINST_FULL,%eax
    FETCH_INST_WORD(2)
    jp       .LOP_CMPL_FLOAT_isNaN
    je       .LOP_CMPL_FLOAT_finish
    sbbl     %ecx,%ecx
    jb       .LOP_CMPL_FLOAT_finish
    incl     %ecx
.LOP_CMPL_FLOAT_finish:
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_CMPG_FLOAT: /* 0x2e */
/* File: x86/OP_CMPG_FLOAT.S */
/* File: x86/OP_CMPG_DOUBLE.S */
    /* float/double_cmp[gl] vAA, vBB, vCC */
    movzbl    3(rPC),%eax             # eax<- CC
    movzbl    2(rPC),%ecx             # ecx<- BB
    .if 0
    fldl     (rFP,%eax,4)
    fldl     (rFP,%ecx,4)
    .else
    flds     (rFP,%eax,4)
    flds     (rFP,%ecx,4)
    .endif
    movzbl   rINST_HI,rINST_FULL
    xorl     %ecx,%ecx
    fucompp     # z if equal, p set if NaN, c set if st0 < st1
    fnstsw   %ax
    sahf
    movl      rINST_FULL,%eax
    FETCH_INST_WORD(2)
    jp       .LOP_CMPG_FLOAT_isNaN
    je       .LOP_CMPG_FLOAT_finish
    sbbl     %ecx,%ecx
    jb       .LOP_CMPG_FLOAT_finish
    incl     %ecx
.LOP_CMPG_FLOAT_finish:
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_CMPL_DOUBLE: /* 0x2f */
/* File: x86/OP_CMPL_DOUBLE.S */
/* File: x86/OP_CMPG_DOUBLE.S */
    /* float/double_cmp[gl] vAA, vBB, vCC */
    movzbl    3(rPC),%eax             # eax<- CC
    movzbl    2(rPC),%ecx             # ecx<- BB
    .if 1
    fldl     (rFP,%eax,4)
    fldl     (rFP,%ecx,4)
    .else
    flds     (rFP,%eax,4)
    flds     (rFP,%ecx,4)
    .endif
    movzbl   rINST_HI,rINST_FULL
    xorl     %ecx,%ecx
    fucompp     # z if equal, p set if NaN, c set if st0 < st1
    fnstsw   %ax
    sahf
    movl      rINST_FULL,%eax
    FETCH_INST_WORD(2)
    jp       .LOP_CMPL_DOUBLE_isNaN
    je       .LOP_CMPL_DOUBLE_finish
    sbbl     %ecx,%ecx
    jb       .LOP_CMPL_DOUBLE_finish
    incl     %ecx
.LOP_CMPL_DOUBLE_finish:
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_CMPG_DOUBLE: /* 0x30 */
/* File: x86/OP_CMPG_DOUBLE.S */
    /* float/double_cmp[gl] vAA, vBB, vCC */
    movzbl    3(rPC),%eax             # eax<- CC
    movzbl    2(rPC),%ecx             # ecx<- BB
    .if 1
    fldl     (rFP,%eax,4)
    fldl     (rFP,%ecx,4)
    .else
    flds     (rFP,%eax,4)
    flds     (rFP,%ecx,4)
    .endif
    movzbl   rINST_HI,rINST_FULL
    xorl     %ecx,%ecx
    fucompp     # z if equal, p set if NaN, c set if st0 < st1
    fnstsw   %ax
    sahf
    movl      rINST_FULL,%eax
    FETCH_INST_WORD(2)
    jp       .LOP_CMPG_DOUBLE_isNaN
    je       .LOP_CMPG_DOUBLE_finish
    sbbl     %ecx,%ecx
    jb       .LOP_CMPG_DOUBLE_finish
    incl     %ecx
.LOP_CMPG_DOUBLE_finish:
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_CMP_LONG: /* 0x31 */
/* File: x86/OP_CMP_LONG.S */
    /*
     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
     * register based on the results of the comparison.
     */
    /* cmp-long vAA, vBB, vCC */
    movzbl    2(rPC),%ecx              # ecx<- BB
    SPILL(rPC)
    movzbl    3(rPC),rPC               # rPC<- CC
    GET_VREG_WORD(%eax,%ecx,1)         # eax<- v[BB+1]
    GET_VREG_WORD(%ecx,%ecx,0)         # ecx<- v[BB+0]
    movzbl    rINST_HI,rINST_FULL      # rINST_FULL<- AA
    cmpl      4(rFP,rPC,4),%eax
    jl        .LOP_CMP_LONG_smaller
    jg        .LOP_CMP_LONG_bigger
    sub       (rFP,rPC,4),%ecx
    ja        .LOP_CMP_LONG_bigger
    jb        .LOP_CMP_LONG_smaller
    UNSPILL(rPC)
    jmp       .LOP_CMP_LONG_finish

/* ------------------------------ */
    .balign 64
.L_OP_IF_EQ: /* 0x32 */
/* File: x86/OP_IF_EQ.S */
/* File: x86/bincmp.S */
    /*
     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
     */
    /* if-cmp vA, vB, +CCCC */
    movzx    rINST_HI,%ecx              # ecx <- A+
    andb     $0xf,%cl                  # ecx <- A
    GET_VREG(%eax,%ecx)                 # eax <- vA
    sarl     $12,rINST_FULL            # rINST_FULL<- B
    cmpl     (rFP,rINST_FULL,4),%eax    # compare (vA, vB)
    movswl   2(rPC),rINST_FULL          # Get signed branch offset
    movl     $2,%eax                   # assume not taken
    jne   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_NE: /* 0x33 */
/* File: x86/OP_IF_NE.S */
/* File: x86/bincmp.S */
    /*
     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
     */
    /* if-cmp vA, vB, +CCCC */
    movzx    rINST_HI,%ecx              # ecx <- A+
    andb     $0xf,%cl                  # ecx <- A
    GET_VREG(%eax,%ecx)                 # eax <- vA
    sarl     $12,rINST_FULL            # rINST_FULL<- B
    cmpl     (rFP,rINST_FULL,4),%eax    # compare (vA, vB)
    movswl   2(rPC),rINST_FULL          # Get signed branch offset
    movl     $2,%eax                   # assume not taken
    je   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_LT: /* 0x34 */
/* File: x86/OP_IF_LT.S */
/* File: x86/bincmp.S */
    /*
     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
     */
    /* if-cmp vA, vB, +CCCC */
    movzx    rINST_HI,%ecx              # ecx <- A+
    andb     $0xf,%cl                  # ecx <- A
    GET_VREG(%eax,%ecx)                 # eax <- vA
    sarl     $12,rINST_FULL            # rINST_FULL<- B
    cmpl     (rFP,rINST_FULL,4),%eax    # compare (vA, vB)
    movswl   2(rPC),rINST_FULL          # Get signed branch offset
    movl     $2,%eax                   # assume not taken
    jge   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_GE: /* 0x35 */
/* File: x86/OP_IF_GE.S */
/* File: x86/bincmp.S */
    /*
     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
     */
    /* if-cmp vA, vB, +CCCC */
    movzx    rINST_HI,%ecx              # ecx <- A+
    andb     $0xf,%cl                  # ecx <- A
    GET_VREG(%eax,%ecx)                 # eax <- vA
    sarl     $12,rINST_FULL            # rINST_FULL<- B
    cmpl     (rFP,rINST_FULL,4),%eax    # compare (vA, vB)
    movswl   2(rPC),rINST_FULL          # Get signed branch offset
    movl     $2,%eax                   # assume not taken
    jl   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_GT: /* 0x36 */
/* File: x86/OP_IF_GT.S */
/* File: x86/bincmp.S */
    /*
     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
     */
    /* if-cmp vA, vB, +CCCC */
    movzx    rINST_HI,%ecx              # ecx <- A+
    andb     $0xf,%cl                  # ecx <- A
    GET_VREG(%eax,%ecx)                 # eax <- vA
    sarl     $12,rINST_FULL            # rINST_FULL<- B
    cmpl     (rFP,rINST_FULL,4),%eax    # compare (vA, vB)
    movswl   2(rPC),rINST_FULL          # Get signed branch offset
    movl     $2,%eax                   # assume not taken
    jle   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_LE: /* 0x37 */
/* File: x86/OP_IF_LE.S */
/* File: x86/bincmp.S */
    /*
     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
     */
    /* if-cmp vA, vB, +CCCC */
    movzx    rINST_HI,%ecx              # ecx <- A+
    andb     $0xf,%cl                  # ecx <- A
    GET_VREG(%eax,%ecx)                 # eax <- vA
    sarl     $12,rINST_FULL            # rINST_FULL<- B
    cmpl     (rFP,rINST_FULL,4),%eax    # compare (vA, vB)
    movswl   2(rPC),rINST_FULL          # Get signed branch offset
    movl     $2,%eax                   # assume not taken
    jg   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_EQZ: /* 0x38 */
/* File: x86/OP_IF_EQZ.S */
/* File: x86/zcmp.S */
    /*
     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
     */
    /* if-cmp vAA, +BBBB */
    movzx    rINST_HI,%ecx             # ecx <- AA
    cmpl     $0,(rFP,%ecx,4)          # compare (vA, 0)
    movswl   2(rPC),rINST_FULL         # fetch signed displacement
    movl     $2,%eax                  # assume branch not taken
    jne   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_NEZ: /* 0x39 */
/* File: x86/OP_IF_NEZ.S */
/* File: x86/zcmp.S */
    /*
     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
     */
    /* if-cmp vAA, +BBBB */
    movzx    rINST_HI,%ecx             # ecx <- AA
    cmpl     $0,(rFP,%ecx,4)          # compare (vA, 0)
    movswl   2(rPC),rINST_FULL         # fetch signed displacement
    movl     $2,%eax                  # assume branch not taken
    je   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_LTZ: /* 0x3a */
/* File: x86/OP_IF_LTZ.S */
/* File: x86/zcmp.S */
    /*
     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
     */
    /* if-cmp vAA, +BBBB */
    movzx    rINST_HI,%ecx             # ecx <- AA
    cmpl     $0,(rFP,%ecx,4)          # compare (vA, 0)
    movswl   2(rPC),rINST_FULL         # fetch signed displacement
    movl     $2,%eax                  # assume branch not taken
    jge   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_GEZ: /* 0x3b */
/* File: x86/OP_IF_GEZ.S */
/* File: x86/zcmp.S */
    /*
     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
     */
    /* if-cmp vAA, +BBBB */
    movzx    rINST_HI,%ecx             # ecx <- AA
    cmpl     $0,(rFP,%ecx,4)          # compare (vA, 0)
    movswl   2(rPC),rINST_FULL         # fetch signed displacement
    movl     $2,%eax                  # assume branch not taken
    jl   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_GTZ: /* 0x3c */
/* File: x86/OP_IF_GTZ.S */
/* File: x86/zcmp.S */
    /*
     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
     */
    /* if-cmp vAA, +BBBB */
    movzx    rINST_HI,%ecx             # ecx <- AA
    cmpl     $0,(rFP,%ecx,4)          # compare (vA, 0)
    movswl   2(rPC),rINST_FULL         # fetch signed displacement
    movl     $2,%eax                  # assume branch not taken
    jle   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IF_LEZ: /* 0x3d */
/* File: x86/OP_IF_LEZ.S */
/* File: x86/zcmp.S */
    /*
     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
     * fragment that specifies the *reverse* comparison to perform, e.g.
     * for "if-le" you would use "gt".
     *
     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
     */
    /* if-cmp vAA, +BBBB */
    movzx    rINST_HI,%ecx             # ecx <- AA
    cmpl     $0,(rFP,%ecx,4)          # compare (vA, 0)
    movswl   2(rPC),rINST_FULL         # fetch signed displacement
    movl     $2,%eax                  # assume branch not taken
    jg   1f
    testl    rINST_FULL,rINST_FULL
    js       common_backwardBranch
    movl     rINST_FULL,%eax
1:
    FETCH_INST_INDEXED(%eax)
    ADVANCE_PC_INDEXED(%eax)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_3E: /* 0x3e */
/* File: x86/OP_UNUSED_3E.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_3F: /* 0x3f */
/* File: x86/OP_UNUSED_3F.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_40: /* 0x40 */
/* File: x86/OP_UNUSED_40.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_41: /* 0x41 */
/* File: x86/OP_UNUSED_41.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_42: /* 0x42 */
/* File: x86/OP_UNUSED_42.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_43: /* 0x43 */
/* File: x86/OP_UNUSED_43.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_AGET: /* 0x44 */
/* File: x86/OP_AGET.S */
    /*
     * Array get, 32 bits or less.  vAA <- vBB[vCC].
     *
     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    movl     offArrayObject_contents(%eax,%ecx,4),%eax
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_AGET_WIDE: /* 0x45 */
/* File: x86/OP_AGET_WIDE.S */
    /*
     * Array get, 64 bits.  vAA <- vBB[vCC].
     *
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jb        .LOP_AGET_WIDE_finish        # index < length, OK
    jmp       common_errArrayIndex      # index >= length, bail

/* ------------------------------ */
    .balign 64
.L_OP_AGET_OBJECT: /* 0x46 */
/* File: x86/OP_AGET_OBJECT.S */
/* File: x86/OP_AGET.S */
    /*
     * Array get, 32 bits or less.  vAA <- vBB[vCC].
     *
     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    movl     offArrayObject_contents(%eax,%ecx,4),%eax
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_AGET_BOOLEAN: /* 0x47 */
/* File: x86/OP_AGET_BOOLEAN.S */
/* File: x86/OP_AGET.S */
    /*
     * Array get, 32 bits or less.  vAA <- vBB[vCC].
     *
     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    movzbl     offArrayObject_contents(%eax,%ecx,1),%eax
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_AGET_BYTE: /* 0x48 */
/* File: x86/OP_AGET_BYTE.S */
/* File: x86/OP_AGET.S */
    /*
     * Array get, 32 bits or less.  vAA <- vBB[vCC].
     *
     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    movsbl     offArrayObject_contents(%eax,%ecx,1),%eax
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_AGET_CHAR: /* 0x49 */
/* File: x86/OP_AGET_CHAR.S */
/* File: x86/OP_AGET.S */
    /*
     * Array get, 32 bits or less.  vAA <- vBB[vCC].
     *
     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    movzwl     offArrayObject_contents(%eax,%ecx,2),%eax
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_AGET_SHORT: /* 0x4a */
/* File: x86/OP_AGET_SHORT.S */
/* File: x86/OP_AGET.S */
    /*
     * Array get, 32 bits or less.  vAA <- vBB[vCC].
     *
     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    movswl     offArrayObject_contents(%eax,%ecx,2),%eax
    movl      rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_APUT: /* 0x4b */
/* File: x86/OP_APUT.S */
    /*
     * Array put, 32 bits or less.  vBB[vCC] <- vAA
     *
     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    leal      offArrayObject_contents(%eax,%ecx,4),%eax
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    movl     %ecx,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_APUT_WIDE: /* 0x4c */
/* File: x86/OP_APUT_WIDE.S */
    /*
     * Array put, 64 bits.  vBB[vCC]<-vAA.
     *
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jb        .LOP_APUT_WIDE_finish        # index < length, OK
    jmp       common_errArrayIndex      # index >= length, bail

/* ------------------------------ */
    .balign 64
.L_OP_APUT_OBJECT: /* 0x4d */
/* File: x86/OP_APUT_OBJECT.S */
    /*
     * Array put, 32 bits or less.  vBB[vCC] <- vAA
     *
     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- vAA
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jb        .LOP_APUT_OBJECT_continue
    jmp       common_errArrayIndex      # index >= length, bail

/* ------------------------------ */
    .balign 64
.L_OP_APUT_BOOLEAN: /* 0x4e */
/* File: x86/OP_APUT_BOOLEAN.S */
/* File: x86/OP_APUT.S */
    /*
     * Array put, 32 bits or less.  vBB[vCC] <- vAA
     *
     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    leal      offArrayObject_contents(%eax,%ecx,1),%eax
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    movb     %cl,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_APUT_BYTE: /* 0x4f */
/* File: x86/OP_APUT_BYTE.S */
/* File: x86/OP_APUT.S */
    /*
     * Array put, 32 bits or less.  vBB[vCC] <- vAA
     *
     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    leal      offArrayObject_contents(%eax,%ecx,1),%eax
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    movb     %cl,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_APUT_CHAR: /* 0x50 */
/* File: x86/OP_APUT_CHAR.S */
/* File: x86/OP_APUT.S */
    /*
     * Array put, 32 bits or less.  vBB[vCC] <- vAA
     *
     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    leal      offArrayObject_contents(%eax,%ecx,2),%eax
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    movw     %cx,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_APUT_SHORT: /* 0x51 */
/* File: x86/OP_APUT_SHORT.S */
/* File: x86/OP_APUT.S */
    /*
     * Array put, 32 bits or less.  vBB[vCC] <- vAA
     *
     * for: aput, aput-object, aput-boolean, aput-byte, aput-char, aput-short
     */
    /* op vAA, vBB, vCC */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    GET_VREG(%eax,%eax)                 # eax<- vBB (array object)
    GET_VREG(%ecx,%ecx)                 # ecs<- vCC (requested index)
    testl     %eax,%eax                 # null array object?
    je        common_errNullObject      # bail if so
    cmpl      offArrayObject_length(%eax),%ecx
    jae       common_errArrayIndex      # index >= length, bail
    leal      offArrayObject_contents(%eax,%ecx,2),%eax
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    movw     %cx,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IGET: /* 0x52 */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_resolve

/* ------------------------------ */
    .balign 64
.L_OP_IGET_WIDE: /* 0x53 */
/* File: x86/OP_IGET_WIDE.S */
    /*
     * 64-bit instance field get.
     *
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_WIDE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_WIDE_resolve

/* ------------------------------ */
    .balign 64
.L_OP_IGET_OBJECT: /* 0x54 */
/* File: x86/OP_IGET_OBJECT.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_OBJECT_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_OBJECT_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IGET_BOOLEAN: /* 0x55 */
/* File: x86/OP_IGET_BOOLEAN.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_BOOLEAN_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_BOOLEAN_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IGET_BYTE: /* 0x56 */
/* File: x86/OP_IGET_BYTE.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_BYTE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_BYTE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IGET_CHAR: /* 0x57 */
/* File: x86/OP_IGET_CHAR.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_CHAR_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_CHAR_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IGET_SHORT: /* 0x58 */
/* File: x86/OP_IGET_SHORT.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_SHORT_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_SHORT_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IPUT: /* 0x59 */
/* File: x86/OP_IPUT.S */

    /*
     * General 32-bit instance field put.
     *
     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_resolve

/* ------------------------------ */
    .balign 64
.L_OP_IPUT_WIDE: /* 0x5a */
/* File: x86/OP_IPUT_WIDE.S */
    /*
     * 64-bit instance field put.
     *
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_WIDE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_WIDE_resolve

/* ------------------------------ */
    .balign 64
.L_OP_IPUT_OBJECT: /* 0x5b */
/* File: x86/OP_IPUT_OBJECT.S */
    /*
     * Object field put.
     *
     * for: iput-object
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_OBJECT_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_OBJECT_resolve

/* ------------------------------ */
    .balign 64
.L_OP_IPUT_BOOLEAN: /* 0x5c */
/* File: x86/OP_IPUT_BOOLEAN.S */
/* File: x86/OP_IPUT.S */

    /*
     * General 32-bit instance field put.
     *
     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_BOOLEAN_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_BOOLEAN_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IPUT_BYTE: /* 0x5d */
/* File: x86/OP_IPUT_BYTE.S */
/* File: x86/OP_IPUT.S */

    /*
     * General 32-bit instance field put.
     *
     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_BYTE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_BYTE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IPUT_CHAR: /* 0x5e */
/* File: x86/OP_IPUT_CHAR.S */
/* File: x86/OP_IPUT.S */

    /*
     * General 32-bit instance field put.
     *
     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_CHAR_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_CHAR_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IPUT_SHORT: /* 0x5f */
/* File: x86/OP_IPUT_SHORT.S */
/* File: x86/OP_IPUT.S */

    /*
     * General 32-bit instance field put.
     *
     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_SHORT_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_SHORT_resolve


/* ------------------------------ */
    .balign 64
.L_OP_SGET: /* 0x60 */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_resolve                # if not, make it so
.LOP_SGET_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_SGET_WIDE: /* 0x61 */
/* File: x86/OP_SGET_WIDE.S */
    /*
     * 64-bit SGET handler.
     *
     */
    /* sget-wide vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_WIDE_resolve                # if not, make it so
.LOP_SGET_WIDE_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%ecx    # ecx<- lsw
    movl      4+offStaticField_value(%eax),%eax  # eax<- msw
    movzbl    rINST_HI,rINST_FULL                # rINST_FULL<- AA
    SET_VREG_WORD(%ecx,rINST_FULL,0)
    SET_VREG_WORD(%eax,rINST_FULL,1)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_SGET_OBJECT: /* 0x62 */
/* File: x86/OP_SGET_OBJECT.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_OBJECT_resolve                # if not, make it so
.LOP_SGET_OBJECT_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SGET_BOOLEAN: /* 0x63 */
/* File: x86/OP_SGET_BOOLEAN.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_BOOLEAN_resolve                # if not, make it so
.LOP_SGET_BOOLEAN_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SGET_BYTE: /* 0x64 */
/* File: x86/OP_SGET_BYTE.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_BYTE_resolve                # if not, make it so
.LOP_SGET_BYTE_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SGET_CHAR: /* 0x65 */
/* File: x86/OP_SGET_CHAR.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_CHAR_resolve                # if not, make it so
.LOP_SGET_CHAR_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SGET_SHORT: /* 0x66 */
/* File: x86/OP_SGET_SHORT.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_SHORT_resolve                # if not, make it so
.LOP_SGET_SHORT_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SPUT: /* 0x67 */
/* File: x86/OP_SPUT.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_resolve                # if not, make it so
.LOP_SPUT_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(2)
    movl      %ecx,offStaticField_value(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_SPUT_WIDE: /* 0x68 */
/* File: x86/OP_SPUT_WIDE.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_WIDE_resolve                # if not, make it so
.LOP_SPUT_WIDE_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG_WORD(rINST_FULL,%ecx,0)             # rINST_FULL<- lsw
    GET_VREG_WORD(%ecx,%ecx,1)                   # ecx<- msw
    movl      rINST_FULL,offStaticField_value(%eax)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    movl      %ecx,4+offStaticField_value(%eax)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_SPUT_OBJECT: /* 0x69 */
/* File: x86/OP_SPUT_OBJECT.S */
    /*
     * SPUT object handler.
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_OBJECT_resolve                # if not, make it so
.LOP_SPUT_OBJECT_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    jmp       .LOP_SPUT_OBJECT_continue

/* ------------------------------ */
    .balign 64
.L_OP_SPUT_BOOLEAN: /* 0x6a */
/* File: x86/OP_SPUT_BOOLEAN.S */
/* File: x86/OP_SPUT.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_BOOLEAN_resolve                # if not, make it so
.LOP_SPUT_BOOLEAN_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(2)
    movl      %ecx,offStaticField_value(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SPUT_BYTE: /* 0x6b */
/* File: x86/OP_SPUT_BYTE.S */
/* File: x86/OP_SPUT.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_BYTE_resolve                # if not, make it so
.LOP_SPUT_BYTE_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(2)
    movl      %ecx,offStaticField_value(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SPUT_CHAR: /* 0x6c */
/* File: x86/OP_SPUT_CHAR.S */
/* File: x86/OP_SPUT.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_CHAR_resolve                # if not, make it so
.LOP_SPUT_CHAR_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(2)
    movl      %ecx,offStaticField_value(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SPUT_SHORT: /* 0x6d */
/* File: x86/OP_SPUT_SHORT.S */
/* File: x86/OP_SPUT.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_SHORT_resolve                # if not, make it so
.LOP_SPUT_SHORT_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(2)
    movl      %ecx,offStaticField_value(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_VIRTUAL: /* 0x6e */
/* File: x86/OP_INVOKE_VIRTUAL.S */

    /*
     * Handle a virtual method call.
     *
     * for: invoke-virtual, invoke-virtual/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%eax)
    movzwl    2(rPC),%ecx                 # ecx<- BBBB
    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
    testl     %eax,%eax                   # already resolved?
    jne       .LOP_INVOKE_VIRTUAL_continue        # yes, continue
    GET_GLUE(%eax)
    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
    movl      offGlue_method(%eax),%eax   # eax<- glue->method
    SPILL(rPC)
    jmp       .LOP_INVOKE_VIRTUAL_more

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_SUPER: /* 0x6f */
/* File: x86/OP_INVOKE_SUPER.S */
    /*
     * Handle a "super" method call.
     *
     * for: invoke-super, invoke-super/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(rINST_FULL)
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
    movl      offGlue_method(rINST_FULL),%eax # eax<- method
    movzwl    4(rPC),rINST_FULL         # rINST_FULL<- GFED or CCCC
    .if       (!0)
    andl      $0xf,rINST_FULL          # rINST_FULL<- D (or stays CCCC)
    .endif
    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- "this" ptr
    testl     rINST_FULL,rINST_FULL     # null "this"?
    je        common_errNullObject      # yes, throw
    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
    testl     %ecx,%ecx                 # already resolved?
    jne       .LOP_INVOKE_SUPER_continue      # yes - go on
    jmp       .LOP_INVOKE_SUPER_resolve

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_DIRECT: /* 0x70 */
/* File: x86/OP_INVOKE_DIRECT.S */
    /*
     * Handle a direct method call.
     *
     * (We could defer the "is 'this' pointer null" test to the common
     * method invocation code, and use a flag to indicate that static
     * calls don't count.  If we do this as part of copying the arguments
     * out we could avoiding loading the first arg twice.)
     *
     * for: invoke-direct, invoke-direct/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax              # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
    EXPORT_PC()
    SPILL(rPC)
    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
    movzwl    4(rPC),rPC               # rPC<- GFED or CCCC
    movl      (%ecx,%eax,4),%eax       # eax<- resolved methodToCall
    .if       (!0)
    andl      $0xf,rPC                # rPC<- D (or stays CCCC)
    .endif
    testl     %eax,%eax                # already resolved?
    GET_VREG(%ecx,rPC)                 # ecx<- "this" ptr
    je        .LOP_INVOKE_DIRECT_resolve      # not resolved, do it now
.LOP_INVOKE_DIRECT_finish:
    UNSPILL(rPC)
    testl     %ecx,%ecx                # null "this"?
    jne       common_invokeMethodNoRange  # no, continue on
    jmp       common_errNullObject

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_STATIC: /* 0x71 */
/* File: x86/OP_INVOKE_STATIC.S */
    /*
     * Handle a static method call.
     *
     * for: invoke-static, invoke-static/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
    movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
    testl     %eax,%eax
    jne       common_invokeMethodNoRange
    GET_GLUE(%ecx)
    movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
    movzwl    2(rPC),%eax
    movl      offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
    movl      %eax,OUT_ARG1(%esp)       # arg1<- BBBB
    movl      %ecx,OUT_ARG0(%esp)       # arg0<- clazz
    jmp       .LOP_INVOKE_STATIC_continue

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_INTERFACE: /* 0x72 */
/* File: x86/OP_INVOKE_INTERFACE.S */
    /*
     * Handle an interface method call.
     *
     * for: invoke-interface, invoke-interface/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    movzwl     4(rPC),%eax              # eax<- FEDC or CCCC
    GET_GLUE(%ecx)
    .if        (!0)
    andl       $0xf,%eax               # eax<- C (or stays CCCC)
    .endif
    GET_VREG(%eax,%eax)                 # eax<- "this"
    EXPORT_PC()
    testl      %eax,%eax                # null this?
    je         common_errNullObject     # yes, fail
    movl       offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
    movl       %eax,OUT_ARG0(%esp)                 # arg0<- class
    movl       offGlue_methodClassDex(%ecx),%eax   # eax<- methodClassDex
    movl       offGlue_method(%ecx),%ecx           # ecx<- method
    movl       %eax,OUT_ARG3(%esp)                 # arg3<- dex
    movzwl     2(rPC),%eax                         # eax<- BBBB
    movl       %ecx,OUT_ARG2(%esp)                 # arg2<- method
    movl       %eax,OUT_ARG1(%esp)                 # arg1<- BBBB
    SPILL(rPC)
    jmp        .LOP_INVOKE_INTERFACE_continue

/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_73: /* 0x73 */
/* File: x86/OP_UNUSED_73.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
/* File: x86/OP_INVOKE_VIRTUAL_RANGE.S */
/* File: x86/OP_INVOKE_VIRTUAL.S */

    /*
     * Handle a virtual method call.
     *
     * for: invoke-virtual, invoke-virtual/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%eax)
    movzwl    2(rPC),%ecx                 # ecx<- BBBB
    movl      offGlue_methodClassDex(%eax),%eax  # eax<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%eax),%eax   # eax<- pDvmDex->pResMethods
    movl      (%eax,%ecx,4),%eax          # eax<- resolved baseMethod
    testl     %eax,%eax                   # already resolved?
    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # yes, continue
    GET_GLUE(%eax)
    movl      %ecx,OUT_ARG1(%esp)         # arg1<- ref
    movl      offGlue_method(%eax),%eax   # eax<- glue->method
    SPILL(rPC)
    jmp       .LOP_INVOKE_VIRTUAL_RANGE_more


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
/* File: x86/OP_INVOKE_SUPER_RANGE.S */
/* File: x86/OP_INVOKE_SUPER.S */
    /*
     * Handle a "super" method call.
     *
     * for: invoke-super, invoke-super/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(rINST_FULL)
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offGlue_methodClassDex(rINST_FULL),%ecx # ecx<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%ecx),%ecx # ecx<- pDvmDex->pResMethods
    movl      (%ecx,%eax,4),%ecx        # ecx<- resolved baseMethod
    movl      offGlue_method(rINST_FULL),%eax # eax<- method
    movzwl    4(rPC),rINST_FULL         # rINST_FULL<- GFED or CCCC
    .if       (!1)
    andl      $0xf,rINST_FULL          # rINST_FULL<- D (or stays CCCC)
    .endif
    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- "this" ptr
    testl     rINST_FULL,rINST_FULL     # null "this"?
    je        common_errNullObject      # yes, throw
    movl      offMethod_clazz(%eax),%eax # eax<- method->clazz
    testl     %ecx,%ecx                 # already resolved?
    jne       .LOP_INVOKE_SUPER_RANGE_continue      # yes - go on
    jmp       .LOP_INVOKE_SUPER_RANGE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
/* File: x86/OP_INVOKE_DIRECT_RANGE.S */
/* File: x86/OP_INVOKE_DIRECT.S */
    /*
     * Handle a direct method call.
     *
     * (We could defer the "is 'this' pointer null" test to the common
     * method invocation code, and use a flag to indicate that static
     * calls don't count.  If we do this as part of copying the arguments
     * out we could avoiding loading the first arg twice.)
     *
     * for: invoke-direct, invoke-direct/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax              # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
    EXPORT_PC()
    SPILL(rPC)
    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
    movzwl    4(rPC),rPC               # rPC<- GFED or CCCC
    movl      (%ecx,%eax,4),%eax       # eax<- resolved methodToCall
    .if       (!1)
    andl      $0xf,rPC                # rPC<- D (or stays CCCC)
    .endif
    testl     %eax,%eax                # already resolved?
    GET_VREG(%ecx,rPC)                 # ecx<- "this" ptr
    je        .LOP_INVOKE_DIRECT_RANGE_resolve      # not resolved, do it now
.LOP_INVOKE_DIRECT_RANGE_finish:
    UNSPILL(rPC)
    testl     %ecx,%ecx                # null "this"?
    jne       common_invokeMethodRange  # no, continue on
    jmp       common_errNullObject


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
/* File: x86/OP_INVOKE_STATIC_RANGE.S */
/* File: x86/OP_INVOKE_STATIC.S */
    /*
     * Handle a static method call.
     *
     * for: invoke-static, invoke-static/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx # ecx<- pDvmDex
    EXPORT_PC()
    movl      offDvmDex_pResMethods(%ecx),%ecx  # ecx<- pDvmDex->pResMethods
    movl      (%ecx,%eax,4),%eax        # eax<- resolved methodToCall
    testl     %eax,%eax
    jne       common_invokeMethodRange
    GET_GLUE(%ecx)
    movl      offGlue_method(%ecx),%ecx # ecx<- glue->method
    movzwl    2(rPC),%eax
    movl      offMethod_clazz(%ecx),%ecx# ecx<- method->clazz
    movl      %eax,OUT_ARG1(%esp)       # arg1<- BBBB
    movl      %ecx,OUT_ARG0(%esp)       # arg0<- clazz
    jmp       .LOP_INVOKE_STATIC_RANGE_continue


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
/* File: x86/OP_INVOKE_INTERFACE_RANGE.S */
/* File: x86/OP_INVOKE_INTERFACE.S */
    /*
     * Handle an interface method call.
     *
     * for: invoke-interface, invoke-interface/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    movzwl     4(rPC),%eax              # eax<- FEDC or CCCC
    GET_GLUE(%ecx)
    .if        (!1)
    andl       $0xf,%eax               # eax<- C (or stays CCCC)
    .endif
    GET_VREG(%eax,%eax)                 # eax<- "this"
    EXPORT_PC()
    testl      %eax,%eax                # null this?
    je         common_errNullObject     # yes, fail
    movl       offObject_clazz(%eax),%eax# eax<- thisPtr->clazz
    movl       %eax,OUT_ARG0(%esp)                 # arg0<- class
    movl       offGlue_methodClassDex(%ecx),%eax   # eax<- methodClassDex
    movl       offGlue_method(%ecx),%ecx           # ecx<- method
    movl       %eax,OUT_ARG3(%esp)                 # arg3<- dex
    movzwl     2(rPC),%eax                         # eax<- BBBB
    movl       %ecx,OUT_ARG2(%esp)                 # arg2<- method
    movl       %eax,OUT_ARG1(%esp)                 # arg1<- BBBB
    SPILL(rPC)
    jmp        .LOP_INVOKE_INTERFACE_RANGE_continue


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_79: /* 0x79 */
/* File: x86/OP_UNUSED_79.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_7A: /* 0x7a */
/* File: x86/OP_UNUSED_7A.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_NEG_INT: /* 0x7b */
/* File: x86/OP_NEG_INT.S */
/* File: x86/unop.S */
    /*
     * Generic 32-bit unary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = op eax".
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)        # eax<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    
    negl %eax
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_NOT_INT: /* 0x7c */
/* File: x86/OP_NOT_INT.S */
/* File: x86/unop.S */
    /*
     * Generic 32-bit unary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = op eax".
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)        # eax<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    
    notl %eax
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_NEG_LONG: /* 0x7d */
/* File: x86/OP_NEG_LONG.S */
    /* unop vA, vB */
    movzbl    rINST_HI,%ecx            # ecx<- BA
    sarl      $4,%ecx                 # ecx<- B
    movzbl    rINST_HI,rINST_FULL      # ecx<- BA
    andb      $0xf,rINST_LO           # rINST_FULL<- A
    GET_VREG_WORD(%eax,%ecx,0)         # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)         # ecx<- v[B+1]
    negl      %eax
    adcl      $0,%ecx
    negl      %ecx
    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[A+0]<- eax
    SET_VREG_WORD(%ecx,rINST_FULL,1)   # v[A+1]<- ecx
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_NOT_LONG: /* 0x7e */
/* File: x86/OP_NOT_LONG.S */
    /* unop vA, vB */
    movzbl    rINST_HI,%ecx            # ecx<- BA
    sarl      $4,%ecx                 # ecx<- B
    movzbl    rINST_HI,rINST_FULL      # ecx<- BA
    andb      $0xf,rINST_LO           # rINST_FULL<- A
    GET_VREG_WORD(%eax,%ecx,0)         # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)         # ecx<- v[B+1]
    notl      %eax
    notl      %ecx
    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[A+0]<- eax
    SET_VREG_WORD(%ecx,rINST_FULL,1)   # v[A+1]<- ecx
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_NEG_FLOAT: /* 0x7f */
/* File: x86/OP_NEG_FLOAT.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    flds    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fchs
    fstps  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_NEG_DOUBLE: /* 0x80 */
/* File: x86/OP_NEG_DOUBLE.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    fldl    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fchs
    fstpl  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_INT_TO_LONG: /* 0x81 */
/* File: x86/OP_INT_TO_LONG.S */
    /* int to long vA, vB */
    movzbl  rINST_HI,%ecx               # ecx<- +A
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    SPILL(rPC)                          # will step on edx later
    andb    $0xf,%cl                   # ecx<- A
    cltd                                # edx:eax<- sssssssBBBBBBBB
    SET_VREG_WORD(%edx,%ecx,1)          # v[A+1]<- edx/rPC
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)          # v[A+0]<- %eax
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_INT_TO_FLOAT: /* 0x82 */
/* File: x86/OP_INT_TO_FLOAT.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    fildl    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    fstps  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_INT_TO_DOUBLE: /* 0x83 */
/* File: x86/OP_INT_TO_DOUBLE.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    fildl    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    fstpl  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_LONG_TO_INT: /* 0x84 */
/* File: x86/OP_LONG_TO_INT.S */
/* we ignore the high word, making this equivalent to a 32-bit reg move */
/* File: x86/OP_MOVE.S */
    /* for move, move-object, long-to-int */
    /* op vA, vB */
    movzbl rINST_HI,%eax         # eax<- BA
    andb   $0xf,%al             # eax<- A
    shrl   $12,rINST_FULL       # rINST_FULL<- B
    GET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    SET_VREG(%ecx,%eax)          # fp[A]<-fp[B]
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_LONG_TO_FLOAT: /* 0x85 */
/* File: x86/OP_LONG_TO_FLOAT.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    fildll    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    fstps  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_LONG_TO_DOUBLE: /* 0x86 */
/* File: x86/OP_LONG_TO_DOUBLE.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    fildll    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    fstpl  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_FLOAT_TO_INT: /* 0x87 */
/* File: x86/OP_FLOAT_TO_INT.S */
/* File: x86/cvtfp_int.S */
/* On fp to int conversions, Java requires that
 * if the result > maxint, it should be clamped to maxint.  If it is less
 * than minint, it should be clamped to minint.  If it is a nan, the result
 * should be zero.  Further, the rounding mode is to truncate.  This model
 * differs from what is delivered normally via the x86 fpu, so we have
 * to play some games.
 */
    /* float/double to int/long vA, vB */
    movzbl    rINST_HI,%ecx           # ecx<- A+
    sarl      $12,rINST_FULL         # rINST_FULL<- B
    .if 0
    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
    .else
    flds     (rFP,rINST_FULL,4)       # %st0<- vB
    .endif
    ftst
    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
    movzwl   LOCAL0_OFFSET(%ebp),%eax
    movb     $0xc,%ah
    movw     %ax,LOCAL0_OFFSET+2(%ebp)
    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
    FETCH_INST_WORD(1)
    andb     $0xf,%cl                # ecx<- A
    .if 0
    fistpll  (rFP,%ecx,4)             # convert and store
    .else
    fistpl   (rFP,%ecx,4)             # convert and store
    .endif
    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
    jmp      .LOP_FLOAT_TO_INT_continue


/* ------------------------------ */
    .balign 64
.L_OP_FLOAT_TO_LONG: /* 0x88 */
/* File: x86/OP_FLOAT_TO_LONG.S */
/* File: x86/cvtfp_int.S */
/* On fp to int conversions, Java requires that
 * if the result > maxint, it should be clamped to maxint.  If it is less
 * than minint, it should be clamped to minint.  If it is a nan, the result
 * should be zero.  Further, the rounding mode is to truncate.  This model
 * differs from what is delivered normally via the x86 fpu, so we have
 * to play some games.
 */
    /* float/double to int/long vA, vB */
    movzbl    rINST_HI,%ecx           # ecx<- A+
    sarl      $12,rINST_FULL         # rINST_FULL<- B
    .if 0
    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
    .else
    flds     (rFP,rINST_FULL,4)       # %st0<- vB
    .endif
    ftst
    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
    movzwl   LOCAL0_OFFSET(%ebp),%eax
    movb     $0xc,%ah
    movw     %ax,LOCAL0_OFFSET+2(%ebp)
    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
    FETCH_INST_WORD(1)
    andb     $0xf,%cl                # ecx<- A
    .if 1
    fistpll  (rFP,%ecx,4)             # convert and store
    .else
    fistpl   (rFP,%ecx,4)             # convert and store
    .endif
    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
    jmp      .LOP_FLOAT_TO_LONG_continue


/* ------------------------------ */
    .balign 64
.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
/* File: x86/OP_FLOAT_TO_DOUBLE.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    flds    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    fstpl  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_DOUBLE_TO_INT: /* 0x8a */
/* File: x86/OP_DOUBLE_TO_INT.S */
/* File: x86/cvtfp_int.S */
/* On fp to int conversions, Java requires that
 * if the result > maxint, it should be clamped to maxint.  If it is less
 * than minint, it should be clamped to minint.  If it is a nan, the result
 * should be zero.  Further, the rounding mode is to truncate.  This model
 * differs from what is delivered normally via the x86 fpu, so we have
 * to play some games.
 */
    /* float/double to int/long vA, vB */
    movzbl    rINST_HI,%ecx           # ecx<- A+
    sarl      $12,rINST_FULL         # rINST_FULL<- B
    .if 1
    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
    .else
    flds     (rFP,rINST_FULL,4)       # %st0<- vB
    .endif
    ftst
    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
    movzwl   LOCAL0_OFFSET(%ebp),%eax
    movb     $0xc,%ah
    movw     %ax,LOCAL0_OFFSET+2(%ebp)
    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
    FETCH_INST_WORD(1)
    andb     $0xf,%cl                # ecx<- A
    .if 0
    fistpll  (rFP,%ecx,4)             # convert and store
    .else
    fistpl   (rFP,%ecx,4)             # convert and store
    .endif
    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
    jmp      .LOP_DOUBLE_TO_INT_continue


/* ------------------------------ */
    .balign 64
.L_OP_DOUBLE_TO_LONG: /* 0x8b */
/* File: x86/OP_DOUBLE_TO_LONG.S */
/* File: x86/cvtfp_int.S */
/* On fp to int conversions, Java requires that
 * if the result > maxint, it should be clamped to maxint.  If it is less
 * than minint, it should be clamped to minint.  If it is a nan, the result
 * should be zero.  Further, the rounding mode is to truncate.  This model
 * differs from what is delivered normally via the x86 fpu, so we have
 * to play some games.
 */
    /* float/double to int/long vA, vB */
    movzbl    rINST_HI,%ecx           # ecx<- A+
    sarl      $12,rINST_FULL         # rINST_FULL<- B
    .if 1
    fldl     (rFP,rINST_FULL,4)       # %st0<- vB
    .else
    flds     (rFP,rINST_FULL,4)       # %st0<- vB
    .endif
    ftst
    fnstcw   LOCAL0_OFFSET(%ebp)      # remember original rounding mode
    movzwl   LOCAL0_OFFSET(%ebp),%eax
    movb     $0xc,%ah
    movw     %ax,LOCAL0_OFFSET+2(%ebp)
    fldcw    LOCAL0_OFFSET+2(%ebp)      # set "to zero" rounding mode
    FETCH_INST_WORD(1)
    andb     $0xf,%cl                # ecx<- A
    .if 1
    fistpll  (rFP,%ecx,4)             # convert and store
    .else
    fistpl   (rFP,%ecx,4)             # convert and store
    .endif
    fldcw    LOCAL0_OFFSET(%ebp)      # restore previous rounding mode
    jmp      .LOP_DOUBLE_TO_LONG_continue


/* ------------------------------ */
    .balign 64
.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
/* File: x86/OP_DOUBLE_TO_FLOAT.S */
/* File: x86/fpcvt.S */
    /*
     * Generic 32-bit FP conversion operation.
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    fldl    (rFP,rINST_FULL,4)      # %st0<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    fstps  (rFP,%ecx,4)             # vA<- %st0
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_INT_TO_BYTE: /* 0x8d */
/* File: x86/OP_INT_TO_BYTE.S */
/* File: x86/unop.S */
    /*
     * Generic 32-bit unary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = op eax".
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)        # eax<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    
    movsbl %al,%eax
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_INT_TO_CHAR: /* 0x8e */
/* File: x86/OP_INT_TO_CHAR.S */
/* File: x86/unop.S */
    /*
     * Generic 32-bit unary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = op eax".
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)        # eax<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    
    movzwl %ax,%eax
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_INT_TO_SHORT: /* 0x8f */
/* File: x86/OP_INT_TO_SHORT.S */
/* File: x86/unop.S */
    /*
     * Generic 32-bit unary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = op eax".
     */
    /* unop vA, vB */
    movzbl   rINST_HI,%ecx           # ecx<- A+
    sarl     $12,rINST_FULL         # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)        # eax<- vB
    andb     $0xf,%cl               # ecx<- A
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    
    
    movswl %ax,%eax
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_ADD_INT: /* 0x90 */
/* File: x86/OP_ADD_INT.S */
/* File: x86/binop.S */
    /*
     * Generic 32-bit binary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int, sub-int, and-int, or-int,
     *      xor-int, shl-int, shr-int, ushr-int
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    addl (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_INT: /* 0x91 */
/* File: x86/OP_SUB_INT.S */
/* File: x86/binop.S */
    /*
     * Generic 32-bit binary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int, sub-int, and-int, or-int,
     *      xor-int, shl-int, shr-int, ushr-int
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    subl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_INT: /* 0x92 */
/* File: x86/OP_MUL_INT.S */
    /*
     * 32-bit binary multiplication.
     */
    /* mul vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    SPILL(rPC)
    GET_VREG(%eax,%eax)             # eax<- vBB
    imull    (rFP,%ecx,4),%eax      # trashes rPC/edx
    UNSPILL(rPC)
    movzbl   rINST_HI,%ecx          # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_DIV_INT: /* 0x93 */
/* File: x86/OP_DIV_INT.S */
/* File: x86/bindiv.S */

    /*
     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
     * op1=-1.
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $-1,%ecx
    jne      .LOP_DIV_INT_continue_div
    cmpl     $0x80000000,%eax
    jne      .LOP_DIV_INT_continue_div
    movl     $0x80000000,%eax
    jmp      .LOP_DIV_INT_finish_div



/* ------------------------------ */
    .balign 64
.L_OP_REM_INT: /* 0x94 */
/* File: x86/OP_REM_INT.S */
/* File: x86/bindiv.S */

    /*
     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
     * op1=-1.
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $-1,%ecx
    jne      .LOP_REM_INT_continue_div
    cmpl     $0x80000000,%eax
    jne      .LOP_REM_INT_continue_div
    movl     $0,%edx
    jmp      .LOP_REM_INT_finish_div



/* ------------------------------ */
    .balign 64
.L_OP_AND_INT: /* 0x95 */
/* File: x86/OP_AND_INT.S */
/* File: x86/binop.S */
    /*
     * Generic 32-bit binary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int, sub-int, and-int, or-int,
     *      xor-int, shl-int, shr-int, ushr-int
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    andl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_OR_INT: /* 0x96 */
/* File: x86/OP_OR_INT.S */
/* File: x86/binop.S */
    /*
     * Generic 32-bit binary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int, sub-int, and-int, or-int,
     *      xor-int, shl-int, shr-int, ushr-int
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    orl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_XOR_INT: /* 0x97 */
/* File: x86/OP_XOR_INT.S */
/* File: x86/binop.S */
    /*
     * Generic 32-bit binary operation.  Provide an "instr" line that
     * specifies an instruction that performs "result = eax op (rFP,%ecx,4)".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int, sub-int, and-int, or-int,
     *      xor-int, shl-int, shr-int, ushr-int
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    xorl   (rFP,%ecx,4),%eax              # ex: addl    (rFP,%ecx,4),%eax
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHL_INT: /* 0x98 */
/* File: x86/OP_SHL_INT.S */
/* File: x86/binop1.S */
    /*
     * Generic 32-bit binary operation in which both operands loaded to
     * registers (op0 in eax, op1 in ecx).
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    sall    %cl,%eax                          # ex: addl    %ecx,%eax
    movzbl   rINST_HI,%ecx          # tmp<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHR_INT: /* 0x99 */
/* File: x86/OP_SHR_INT.S */
/* File: x86/binop1.S */
    /*
     * Generic 32-bit binary operation in which both operands loaded to
     * registers (op0 in eax, op1 in ecx).
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    sarl    %cl,%eax                          # ex: addl    %ecx,%eax
    movzbl   rINST_HI,%ecx          # tmp<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_USHR_INT: /* 0x9a */
/* File: x86/OP_USHR_INT.S */
/* File: x86/binop1.S */
    /*
     * Generic 32-bit binary operation in which both operands loaded to
     * registers (op0 in eax, op1 in ecx).
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- BB
    movzbl   3(rPC),%ecx            # ecx<- CC
    GET_VREG(%eax,%eax)             # eax<- vBB
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    shrl    %cl,%eax                          # ex: addl    %ecx,%eax
    movzbl   rINST_HI,%ecx          # tmp<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_ADD_LONG: /* 0x9b */
/* File: x86/OP_ADD_LONG.S */
/* File: x86/binopWide.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop vAA, vBB, vCC */

    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
    addl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
    adcl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_LONG: /* 0x9c */
/* File: x86/OP_SUB_LONG.S */
/* File: x86/binopWide.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop vAA, vBB, vCC */

    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
    subl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
    sbbl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_LONG: /* 0x9d */
/* File: x86/OP_MUL_LONG.S */
    /*
     * Signed 64-bit integer multiply.
     *
     * We could definately use more free registers for
     * this code.  We must spill rPC (edx) because it
     * is used by imul.  We'll also spill rINST (ebx),
     * giving us eax, ebc, ecx and edx as computational
     * temps.  On top of that, we'll spill rIBASE (edi)
     * for use as the vB pointer and rFP (esi) for use
     * as the vC pointer.  Yuck.
     */
    /* mul-long vAA, vBB, vCC */
    movzbl    2(rPC),%eax              # eax<- B
    movzbl    3(rPC),%ecx              # ecx<- C
    SPILL(rPC)
    SPILL(rIBASE)
    SPILL(rFP)
    SPILL(rINST_FULL)
    leal      (rFP,%eax,4),rIBASE      # rIBASE<- &v[B]
    leal      (rFP,%ecx,4),rFP         # rFP<- &v[C]
    movl      4(rIBASE),%ecx      # ecx<- Bmsw
    imull     (rFP),%ecx          # ecx<- (Bmsw*Clsw)
    movl      4(rFP),%eax         # eax<- Cmsw
    imull     (rIBASE),%eax       # eax<- (Cmsw*Blsw)
    addl      %eax,%ecx           # ecx<- (Bmsw*Clsw)+(Cmsw*Blsw)
    movl      (rFP),%eax          # eax<- Clsw
    mull      (rIBASE)            # eax<- (Clsw*Alsw)
    UNSPILL(rINST_FULL)
    UNSPILL(rFP)
    jmp       .LOP_MUL_LONG_continue

/* ------------------------------ */
    .balign 64
.L_OP_DIV_LONG: /* 0x9e */
/* File: x86/OP_DIV_LONG.S */
    /* div vAA, vBB, vCC */
    movzbl    3(rPC),%eax              # eax<- CC
    movzbl    2(rPC),%ecx              # ecx<- BB
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)
    GET_VREG_WORD(%eax,%eax,1)
    movl     rPC,OUT_ARG2(%esp)
    testl    %eax,%eax
    je       .LOP_DIV_LONG_check_zero
    cmpl     $-1,%eax
    je       .LOP_DIV_LONG_check_neg1
.LOP_DIV_LONG_notSpecial:
    GET_VREG_WORD(rPC,%ecx,0)
    GET_VREG_WORD(%ecx,%ecx,1)
.LOP_DIV_LONG_notSpecial1:
    movl     %eax,OUT_ARG3(%esp)
    movl     rPC,OUT_ARG0(%esp)
    movl     %ecx,OUT_ARG1(%esp)
    jmp      .LOP_DIV_LONG_continue

/* ------------------------------ */
    .balign 64
.L_OP_REM_LONG: /* 0x9f */
/* File: x86/OP_REM_LONG.S */
/* File: x86/OP_DIV_LONG.S */
    /* div vAA, vBB, vCC */
    movzbl    3(rPC),%eax              # eax<- CC
    movzbl    2(rPC),%ecx              # ecx<- BB
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)
    GET_VREG_WORD(%eax,%eax,1)
    movl     rPC,OUT_ARG2(%esp)
    testl    %eax,%eax
    je       .LOP_REM_LONG_check_zero
    cmpl     $-1,%eax
    je       .LOP_REM_LONG_check_neg1
.LOP_REM_LONG_notSpecial:
    GET_VREG_WORD(rPC,%ecx,0)
    GET_VREG_WORD(%ecx,%ecx,1)
.LOP_REM_LONG_notSpecial1:
    movl     %eax,OUT_ARG3(%esp)
    movl     rPC,OUT_ARG0(%esp)
    movl     %ecx,OUT_ARG1(%esp)
    jmp      .LOP_REM_LONG_continue


/* ------------------------------ */
    .balign 64
.L_OP_AND_LONG: /* 0xa0 */
/* File: x86/OP_AND_LONG.S */
/* File: x86/binopWide.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop vAA, vBB, vCC */

    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
    andl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
    andl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_OR_LONG: /* 0xa1 */
/* File: x86/OP_OR_LONG.S */
/* File: x86/binopWide.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop vAA, vBB, vCC */

    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
    orl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
    orl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_XOR_LONG: /* 0xa2 */
/* File: x86/OP_XOR_LONG.S */
/* File: x86/binopWide.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop vAA, vBB, vCC */

    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)           # rPC<- v[BB+0]
    GET_VREG_WORD(%eax,%eax,1)          # eax<- v[BB+1]
    xorl (rFP,%ecx,4),rPC         # ex: addl   (rFP,%ecx,4),rPC
    xorl 4(rFP,%ecx,4),%eax         # ex: adcl   4(rFP,%ecx,4),%eax
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- AA
    SET_VREG_WORD(rPC,rINST_FULL,0)     # v[AA+0] <- rPC
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[AA+1] <- eax
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHL_LONG: /* 0xa3 */
/* File: x86/OP_SHL_LONG.S */
    /*
     * Long integer shift.  This is different from the generic 32/64-bit
     * binary operations because vAA/vBB are 64-bit but vCC (the shift
     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
     * 6 bits of the shift distance.  x86 shifts automatically mask off
     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
     * case specially.
     */
    /* shl-long vAA, vBB, vCC */
    /* ecx gets shift count */
    /* Need to spill edx */
    /* rINST gets AA */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)                          # spill edx
    GET_VREG_WORD(%edx,%eax,1)          # ecx<- v[BB+1]
    GET_VREG  (%ecx,%ecx)               # ecx<- vCC
    GET_VREG_WORD(%eax,%eax,0)          # eax<- v[BB+0]
    shldl     %eax,%edx
    sall      %cl,%eax
    testb     $32,%cl
    je        2f
    movl      %eax,%edx
    xorl      %eax,%eax
2:
    movzbl    rINST_HI,%ecx
    SET_VREG_WORD(%edx,%ecx,1)         # v[AA+1]<- %edx
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    jmp       .LOP_SHL_LONG_finish

/* ------------------------------ */
    .balign 64
.L_OP_SHR_LONG: /* 0xa4 */
/* File: x86/OP_SHR_LONG.S */
    /*
     * Long integer shift.  This is different from the generic 32/64-bit
     * binary operations because vAA/vBB are 64-bit but vCC (the shift
     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
     * 6 bits of the shift distance.  x86 shifts automatically mask off
     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
     * case specially.
     */
    /* shr-long vAA, vBB, vCC */
    /* ecx gets shift count */
    /* Need to spill edx */
    /* rINST gets AA */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)                          # spill edx
    GET_VREG_WORD(%edx,%eax,1)          # edx<- v[BB+1]
    GET_VREG  (%ecx,%ecx)               # ecx<- vCC
    GET_VREG_WORD(%eax,%eax,0)          # eax<- v[BB+0]
    shrdl     %edx,%eax
    sarl      %cl,%edx
    testb     $32,%cl
    je        2f
    movl      %edx,%eax
    sarl      $31,%edx
2:
    movzbl    rINST_HI,%ecx
    SET_VREG_WORD(%edx,%ecx,1)         # v[AA+1]<- edx
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    jmp       .LOP_SHR_LONG_finish

/* ------------------------------ */
    .balign 64
.L_OP_USHR_LONG: /* 0xa5 */
/* File: x86/OP_USHR_LONG.S */
    /*
     * Long integer shift.  This is different from the generic 32/64-bit
     * binary operations because vAA/vBB are 64-bit but vCC (the shift
     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
     * 6 bits of the shift distance.  x86 shifts automatically mask off
     * the low 5 bits of %cl, so have to handle the 64 > shiftcount > 31
     * case specially.
     */
    /* shr-long vAA, vBB, vCC */
    /* ecx gets shift count */
    /* Need to spill edx */
    /* rINST gets AA */
    movzbl    2(rPC),%eax               # eax<- BB
    movzbl    3(rPC),%ecx               # ecx<- CC
    SPILL(rPC)                          # spill edx
    GET_VREG_WORD(%edx,%eax,1)          # edx<- v[BB+1]
    GET_VREG  (%ecx,%ecx)               # ecx<- vCC
    GET_VREG_WORD(%eax,%eax,0)          # eax<- v[BB+0]
    shrdl     %edx,%eax
    shrl      %cl,%edx
    testb     $32,%cl
    je        2f
    movl      %edx,%eax
    xorl      %edx,%edx
2:
    movzbl    rINST_HI,%ecx
    SET_VREG_WORD(%edx,%ecx,1)         # v[BB+1]<- edx
    UNSPILL(rPC)
    jmp       .LOP_USHR_LONG_finish

/* ------------------------------ */
    .balign 64
.L_OP_ADD_FLOAT: /* 0xa6 */
/* File: x86/OP_ADD_FLOAT.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    flds    (rFP,%eax,4)           # vCC to fp stack
    fadds   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstps   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_FLOAT: /* 0xa7 */
/* File: x86/OP_SUB_FLOAT.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    flds    (rFP,%eax,4)           # vCC to fp stack
    fsubs   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstps   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_FLOAT: /* 0xa8 */
/* File: x86/OP_MUL_FLOAT.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    flds    (rFP,%eax,4)           # vCC to fp stack
    fmuls   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstps   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_DIV_FLOAT: /* 0xa9 */
/* File: x86/OP_DIV_FLOAT.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    flds    (rFP,%eax,4)           # vCC to fp stack
    fdivs   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstps   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_REM_FLOAT: /* 0xaa */
/* File: x86/OP_REM_FLOAT.S */
    /* rem_float vAA, vBB, vCC */
    movzbl   3(rPC),%ecx            # ecx<- BB
    movzbl   2(rPC),%eax            # eax<- CC
    flds     (rFP,%ecx,4)           # vCC to fp stack
    flds     (rFP,%eax,4)           # vCC to fp stack
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
1:
    fprem
    fstsw     %ax
    sahf
    jp        1b
    fstp      %st(1)
    ADVANCE_PC(2)
    fstps    (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_ADD_DOUBLE: /* 0xab */
/* File: x86/OP_ADD_DOUBLE.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    fldl    (rFP,%eax,4)           # vCC to fp stack
    faddl   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstpl   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_DOUBLE: /* 0xac */
/* File: x86/OP_SUB_DOUBLE.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    fldl    (rFP,%eax,4)           # vCC to fp stack
    fsubl   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstpl   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_DOUBLE: /* 0xad */
/* File: x86/OP_MUL_DOUBLE.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    fldl    (rFP,%eax,4)           # vCC to fp stack
    fmull   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstpl   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_DIV_DOUBLE: /* 0xae */
/* File: x86/OP_DIV_DOUBLE.S */
/* File: x86/binflop.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */
    /* binop vAA, vBB, vCC */
    movzbl   2(rPC),%eax            # eax<- CC
    movzbl   3(rPC),%ecx            # ecx<- BB
    fldl    (rFP,%eax,4)           # vCC to fp stack
    fdivl   (rFP,%ecx,4)           # ex: faddp
    movzbl   rINST_HI,%ecx         # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    fstpl   (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_REM_DOUBLE: /* 0xaf */
/* File: x86/OP_REM_DOUBLE.S */
    /* rem_float vAA, vBB, vCC */
    movzbl   3(rPC),%ecx            # ecx<- BB
    movzbl   2(rPC),%eax            # eax<- CC
    fldl     (rFP,%ecx,4)           # vCC to fp stack
    fldl     (rFP,%eax,4)           # vCC to fp stack
    movzbl   rINST_HI,%ecx          # ecx<- AA
    FETCH_INST_WORD(2)
1:
    fprem
    fstsw     %ax
    sahf
    jp        1b
    fstp      %st(1)
    ADVANCE_PC(2)
    fstpl    (rFP,%ecx,4)           # %st to vAA
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_ADD_INT_2ADDR: /* 0xb0 */
/* File: x86/OP_ADD_INT_2ADDR.S */
/* File: x86/binop2addr.S */
    /*
     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = r0 op r1".
     * This could be an ARM instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * If "chkzero" is set to 1, we perform a divide-by-zero check on
     * vCC (r1).  Useful for integer division and modulus.
     *
     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
     */
    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    FETCH_INST_WORD(1)
    andb    $0xf,%cl                   # ecx<- A
    addl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_INT_2ADDR: /* 0xb1 */
/* File: x86/OP_SUB_INT_2ADDR.S */
/* File: x86/binop2addr.S */
    /*
     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = r0 op r1".
     * This could be an ARM instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * If "chkzero" is set to 1, we perform a divide-by-zero check on
     * vCC (r1).  Useful for integer division and modulus.
     *
     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
     */
    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    FETCH_INST_WORD(1)
    andb    $0xf,%cl                   # ecx<- A
    subl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_INT_2ADDR: /* 0xb2 */
/* File: x86/OP_MUL_INT_2ADDR.S */
    /* mul vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    andb    $0xf,%cl                   # ecx<- A
    SPILL(rPC)
    imull   (rFP,%ecx,4),%eax
    UNSPILL(rPC)
    SET_VREG(%eax,%ecx)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_DIV_INT_2ADDR: /* 0xb3 */
/* File: x86/OP_DIV_INT_2ADDR.S */
/* File: x86/bindiv2addr.S */
    /*
     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
     * op1=-1.
     */
    /* div/rem/2addr vA, vB */
    movzx    rINST_HI,%ecx          # eax<- BA
    sarl     $4,%ecx               # ecx<- B
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
    andb     $0xf,rINST_LO         # rINST_FULL<- A
    GET_VREG(%eax,rINST_FULL)       # eax<- vBB
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $-1,%ecx
    jne      .LOP_DIV_INT_2ADDR_continue_div2addr
    cmpl     $0x80000000,%eax
    jne      .LOP_DIV_INT_2ADDR_continue_div2addr
    movl     $0x80000000,%eax
    jmp      .LOP_DIV_INT_2ADDR_finish_div2addr



/* ------------------------------ */
    .balign 64
.L_OP_REM_INT_2ADDR: /* 0xb4 */
/* File: x86/OP_REM_INT_2ADDR.S */
/* File: x86/bindiv2addr.S */
    /*
     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
     * op1=-1.
     */
    /* div/rem/2addr vA, vB */
    movzx    rINST_HI,%ecx          # eax<- BA
    sarl     $4,%ecx               # ecx<- B
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
    andb     $0xf,rINST_LO         # rINST_FULL<- A
    GET_VREG(%eax,rINST_FULL)       # eax<- vBB
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $-1,%ecx
    jne      .LOP_REM_INT_2ADDR_continue_div2addr
    cmpl     $0x80000000,%eax
    jne      .LOP_REM_INT_2ADDR_continue_div2addr
    movl     $0,%edx
    jmp      .LOP_REM_INT_2ADDR_finish_div2addr



/* ------------------------------ */
    .balign 64
.L_OP_AND_INT_2ADDR: /* 0xb5 */
/* File: x86/OP_AND_INT_2ADDR.S */
/* File: x86/binop2addr.S */
    /*
     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = r0 op r1".
     * This could be an ARM instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * If "chkzero" is set to 1, we perform a divide-by-zero check on
     * vCC (r1).  Useful for integer division and modulus.
     *
     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
     */
    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    FETCH_INST_WORD(1)
    andb    $0xf,%cl                   # ecx<- A
    andl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_OR_INT_2ADDR: /* 0xb6 */
/* File: x86/OP_OR_INT_2ADDR.S */
/* File: x86/binop2addr.S */
    /*
     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = r0 op r1".
     * This could be an ARM instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * If "chkzero" is set to 1, we perform a divide-by-zero check on
     * vCC (r1).  Useful for integer division and modulus.
     *
     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
     */
    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    FETCH_INST_WORD(1)
    andb    $0xf,%cl                   # ecx<- A
    orl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_XOR_INT_2ADDR: /* 0xb7 */
/* File: x86/OP_XOR_INT_2ADDR.S */
/* File: x86/binop2addr.S */
    /*
     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = r0 op r1".
     * This could be an ARM instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * If "chkzero" is set to 1, we perform a divide-by-zero check on
     * vCC (r1).  Useful for integer division and modulus.
     *
     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
     */
    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    GET_VREG(%eax,rINST_FULL)           # eax<- vB
    FETCH_INST_WORD(1)
    andb    $0xf,%cl                   # ecx<- A
    xorl     %eax,(rFP,%ecx,4)                              # for ex: addl   %eax,(rFP,%ecx,4)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHL_INT_2ADDR: /* 0xb8 */
/* File: x86/OP_SHL_INT_2ADDR.S */
/* File: x86/shop2addr.S */
    /*
     * Generic 32-bit "shift/2addr" operation.
     */
    /* shift/2addr vA, vB */
    movzx    rINST_HI,%ecx          # eax<- BA
    sarl     $4,%ecx               # ecx<- B
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
    andb     $0xf,rINST_LO         # rINST_FULL<- A
    GET_VREG(%eax,rINST_FULL)       # eax<- vAA
    sall    %cl,%eax                          # ex: sarl %cl,%eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHR_INT_2ADDR: /* 0xb9 */
/* File: x86/OP_SHR_INT_2ADDR.S */
/* File: x86/shop2addr.S */
    /*
     * Generic 32-bit "shift/2addr" operation.
     */
    /* shift/2addr vA, vB */
    movzx    rINST_HI,%ecx          # eax<- BA
    sarl     $4,%ecx               # ecx<- B
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
    andb     $0xf,rINST_LO         # rINST_FULL<- A
    GET_VREG(%eax,rINST_FULL)       # eax<- vAA
    sarl    %cl,%eax                          # ex: sarl %cl,%eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_USHR_INT_2ADDR: /* 0xba */
/* File: x86/OP_USHR_INT_2ADDR.S */
/* File: x86/shop2addr.S */
    /*
     * Generic 32-bit "shift/2addr" operation.
     */
    /* shift/2addr vA, vB */
    movzx    rINST_HI,%ecx          # eax<- BA
    sarl     $4,%ecx               # ecx<- B
    GET_VREG(%ecx,%ecx)             # eax<- vBB
    movzbl   rINST_HI,rINST_FULL    # rINST_FULL<- BA
    andb     $0xf,rINST_LO         # rINST_FULL<- A
    GET_VREG(%eax,rINST_FULL)       # eax<- vAA
    shrl    %cl,%eax                          # ex: sarl %cl,%eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_ADD_LONG_2ADDR: /* 0xbb */
/* File: x86/OP_ADD_LONG_2ADDR.S */
/* File: x86/binopWide2addr.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop/2addr vA, vB */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
    andb      $0xF,rINST_LO            # rINST_FULL<- A
    addl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
    adcl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_LONG_2ADDR: /* 0xbc */
/* File: x86/OP_SUB_LONG_2ADDR.S */
/* File: x86/binopWide2addr.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop/2addr vA, vB */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
    andb      $0xF,rINST_LO            # rINST_FULL<- A
    subl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
    sbbl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_LONG_2ADDR: /* 0xbd */
/* File: x86/OP_MUL_LONG_2ADDR.S */
    /*
     * Signed 64-bit integer multiply, 2-addr version
     *
     * We could definately use more free registers for
     * this code.  We must spill rPC (edx) because it
     * is used by imul.  We'll also spill rINST (ebx),
     * giving us eax, ebc, ecx and edx as computational
     * temps.  On top of that, we'll spill rIBASE (edi)
     * for use as the vA pointer and rFP (esi) for use
     * as the vB pointer.  Yuck.
     */
    /* mul-long/2addr vA, vB */
    movzbl    rINST_HI,%eax            # eax<- BA
    andb      $0xf,%al                # eax<- A
    sarl      $12,rINST_FULL          # rINST_FULL<- B
    SPILL(rPC)
    SPILL(rIBASE)
    SPILL(rFP)
    leal      (rFP,%eax,4),rIBASE      # rIBASE<- &v[A]
    leal      (rFP,rINST_FULL,4),rFP   # rFP<- &v[B]
    movl      4(rIBASE),%ecx      # ecx<- Amsw
    imull     (rFP),%ecx          # ecx<- (Amsw*Blsw)
    movl      4(rFP),%eax         # eax<- Bmsw
    imull     (rIBASE),%eax       # eax<- (Bmsw*Alsw)
    addl      %eax,%ecx           # ecx<- (Amsw*Blsw)+(Bmsw*Alsw)
    movl      (rFP),%eax          # eax<- Blsw
    mull      (rIBASE)            # eax<- (Blsw*Alsw)
    jmp       .LOP_MUL_LONG_2ADDR_continue

/* ------------------------------ */
    .balign 64
.L_OP_DIV_LONG_2ADDR: /* 0xbe */
/* File: x86/OP_DIV_LONG_2ADDR.S */
    /* div/2addr vA, vB */
    movzbl    rINST_HI,%eax
    shrl      $4,%eax                  # eax<- B
    movzbl    rINST_HI,rINST_FULL
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)
    GET_VREG_WORD(%eax,%eax,1)
    movl     rPC,OUT_ARG2(%esp)
    testl    %eax,%eax
    je       .LOP_DIV_LONG_2ADDR_check_zero
    cmpl     $-1,%eax
    je       .LOP_DIV_LONG_2ADDR_check_neg1
.LOP_DIV_LONG_2ADDR_notSpecial:
    GET_VREG_WORD(rPC,rINST_FULL,0)
    GET_VREG_WORD(%ecx,rINST_FULL,1)
.LOP_DIV_LONG_2ADDR_notSpecial1:
    jmp      .LOP_DIV_LONG_2ADDR_continue

/* ------------------------------ */
    .balign 64
.L_OP_REM_LONG_2ADDR: /* 0xbf */
/* File: x86/OP_REM_LONG_2ADDR.S */
/* File: x86/OP_DIV_LONG_2ADDR.S */
    /* div/2addr vA, vB */
    movzbl    rINST_HI,%eax
    shrl      $4,%eax                  # eax<- B
    movzbl    rINST_HI,rINST_FULL
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    SPILL(rPC)
    GET_VREG_WORD(rPC,%eax,0)
    GET_VREG_WORD(%eax,%eax,1)
    movl     rPC,OUT_ARG2(%esp)
    testl    %eax,%eax
    je       .LOP_REM_LONG_2ADDR_check_zero
    cmpl     $-1,%eax
    je       .LOP_REM_LONG_2ADDR_check_neg1
.LOP_REM_LONG_2ADDR_notSpecial:
    GET_VREG_WORD(rPC,rINST_FULL,0)
    GET_VREG_WORD(%ecx,rINST_FULL,1)
.LOP_REM_LONG_2ADDR_notSpecial1:
    jmp      .LOP_REM_LONG_2ADDR_continue


/* ------------------------------ */
    .balign 64
.L_OP_AND_LONG_2ADDR: /* 0xc0 */
/* File: x86/OP_AND_LONG_2ADDR.S */
/* File: x86/binopWide2addr.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop/2addr vA, vB */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
    andb      $0xF,rINST_LO            # rINST_FULL<- A
    andl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
    andl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_OR_LONG_2ADDR: /* 0xc1 */
/* File: x86/OP_OR_LONG_2ADDR.S */
/* File: x86/binopWide2addr.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop/2addr vA, vB */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
    andb      $0xF,rINST_LO            # rINST_FULL<- A
    orl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
    orl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
/* File: x86/OP_XOR_LONG_2ADDR.S */
/* File: x86/binopWide2addr.S */
    /*
     * Generic 64-bit binary operation.
     */
    /* binop/2addr vA, vB */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG_WORD(%eax,%ecx,0)          # eax<- v[B+0]
    GET_VREG_WORD(%ecx,%ecx,1)          # eax<- v[B+1]
    movzbl    rINST_HI,rINST_FULL       # rINST_FULL<- BA
    andb      $0xF,rINST_LO            # rINST_FULL<- A
    xorl %eax,(rFP,rINST_FULL,4)         # example: addl   %eax,(rFP,rINST_FULL,4)
    xorl %ecx,4(rFP,rINST_FULL,4)         # example: adcl   %ecx,4(rFP,rINST_FULL,4)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
/* File: x86/OP_SHL_LONG_2ADDR.S */
    /*
     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
     * 32-bit shift distance.
     */
    /* shl-long/2addr vA, vB */
    /* ecx gets shift count */
    /* Need to spill edx */
    /* rINST gets AA */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    movzbl    rINST_HI,rINST_FULL       # rINST_HI<- BA
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- v[AA+0]
    sarl      $4,%ecx                  # ecx<- B
    SPILL(rPC)
    GET_VREG_WORD(%edx,rINST_FULL,1)    # edx<- v[AA+1]
    GET_VREG(%ecx,%ecx)                 # ecx<- vBB
    shldl     %eax,%edx
    sall      %cl,%eax
    testb     $32,%cl
    je        2f
    movl      %eax,%edx
    xorl      %eax,%eax
2:
    SET_VREG_WORD(%edx,rINST_FULL,1)   # v[AA+1]<- edx
    UNSPILL(rPC)
    jmp       .LOP_SHL_LONG_2ADDR_finish

/* ------------------------------ */
    .balign 64
.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
/* File: x86/OP_SHR_LONG_2ADDR.S */
    /*
     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
     * 32-bit shift distance.
     */
    /* shl-long/2addr vA, vB */
    /* ecx gets shift count */
    /* Need to spill edx */
    /* rINST gets AA */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    movzbl    rINST_HI,rINST_FULL       # rINST_HI<- BA
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- v[AA+0]
    sarl      $4,%ecx                  # ecx<- B
    SPILL(rPC)
    GET_VREG_WORD(%edx,rINST_FULL,1)    # edx<- v[AA+1]
    GET_VREG(%ecx,%ecx)                 # ecx<- vBB
    shrdl     %edx,%eax
    sarl      %cl,%edx
    testb     $32,%cl
    je        2f
    movl      %edx,%eax
    sarl      $31,%edx
2:
    SET_VREG_WORD(%edx,rINST_FULL,1)   # v[AA+1]<- edx
    UNSPILL(rPC)
    jmp       .LOP_SHR_LONG_2ADDR_finish

/* ------------------------------ */
    .balign 64
.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
/* File: x86/OP_USHR_LONG_2ADDR.S */
    /*
     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
     * 32-bit shift distance.
     */
    /* shl-long/2addr vA, vB */
    /* ecx gets shift count */
    /* Need to spill edx */
    /* rINST gets AA */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    movzbl    rINST_HI,rINST_FULL       # rINST_HI<- BA
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- v[AA+0]
    sarl      $4,%ecx                  # ecx<- B
    SPILL(rPC)
    GET_VREG_WORD(%edx,rINST_FULL,1)    # edx<- v[AA+1]
    GET_VREG(%ecx,%ecx)                 # ecx<- vBB
    shrdl     %edx,%eax
    shrl      %cl,%edx
    testb     $32,%cl
    je        2f
    movl      %edx,%eax
    xorl      %edx,%edx
2:
    SET_VREG_WORD(%edx,rINST_FULL,1)   # v[AA+1]<- edx
    UNSPILL(rPC)
    jmp       .LOP_USHR_LONG_2ADDR_finish

/* ------------------------------ */
    .balign 64
.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
/* File: x86/OP_ADD_FLOAT_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    flds    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fadds   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstps    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
/* File: x86/OP_SUB_FLOAT_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    flds    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fsubs   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstps    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
/* File: x86/OP_MUL_FLOAT_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    flds    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fmuls   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstps    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
/* File: x86/OP_DIV_FLOAT_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    flds    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fdivs   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstps    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_REM_FLOAT_2ADDR: /* 0xca */
/* File: x86/OP_REM_FLOAT_2ADDR.S */
    /* rem_float/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    flds     (rFP,rINST_FULL,4)         # vBB to fp stack
    andb    $0xf,%cl                   # ecx<- A
    flds     (rFP,%ecx,4)               # vAA to fp stack
    FETCH_INST_WORD(1)
1:
    fprem
    fstsw     %ax
    sahf
    jp        1b
    fstp      %st(1)
    ADVANCE_PC(1)
    fstps    (rFP,%ecx,4)               # %st to vA
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
/* File: x86/OP_ADD_DOUBLE_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    fldl    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    faddl   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstpl    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
/* File: x86/OP_SUB_DOUBLE_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    fldl    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fsubl   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstpl    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
/* File: x86/OP_MUL_DOUBLE_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    fldl    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fmull   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstpl    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
/* File: x86/OP_DIV_DOUBLE_2ADDR.S */
/* File: x86/binflop2addr.S */
    /*
     * Generic 32-bit binary float operation.
     *
     * For: add-fp, sub-fp, mul-fp, div-fp
     */

    /* binop/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    andb    $0xf,%cl                   # ecx<- A
    fldl    (rFP,%ecx,4)               # vAA to fp stack
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fdivl   (rFP,rINST_FULL,4)           # ex: faddp
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    fstpl    (rFP,%ecx,4)              # %st to vA
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
/* File: x86/OP_REM_DOUBLE_2ADDR.S */
    /* rem_float/2addr vA, vB */
    movzx   rINST_HI,%ecx               # ecx<- A+
    sarl    $12,rINST_FULL             # rINST_FULL<- B
    fldl     (rFP,rINST_FULL,4)         # vBB to fp stack
    andb    $0xf,%cl                   # ecx<- A
    fldl     (rFP,%ecx,4)               # vAA to fp stack
    FETCH_INST_WORD(1)
1:
    fprem
    fstsw     %ax
    sahf
    jp        1b
    fstp      %st(1)
    ADVANCE_PC(1)
    fstpl    (rFP,%ecx,4)               # %st to vA
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_ADD_INT_LIT16: /* 0xd0 */
/* File: x86/OP_ADD_INT_LIT16.S */
/* File: x86/binopLit16.S */
    /*
     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int/lit16, rsub-int,
     *      and-int/lit16, or-int/lit16, xor-int/lit16
     */
    /* binop/lit16 vA, vB, #+CCCC */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    addl %ecx,%eax                              # for example: addl %ecx, %eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_RSUB_INT: /* 0xd1 */
/* File: x86/OP_RSUB_INT.S */
/* File: x86/binopLit16.S */
    /*
     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int/lit16, rsub-int,
     *      and-int/lit16, or-int/lit16, xor-int/lit16
     */
    /* binop/lit16 vA, vB, #+CCCC */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    subl %eax,%ecx                              # for example: addl %ecx, %eax
    SET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_INT_LIT16: /* 0xd2 */
/* File: x86/OP_MUL_INT_LIT16.S */
    /* mul/lit16 vA, vB, #+CCCC */
    /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    SPILL(rPC)
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    imull     %ecx,%eax                 # trashes rPC
    UNSPILL(rPC)
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_DIV_INT_LIT16: /* 0xd3 */
/* File: x86/OP_DIV_INT_LIT16.S */
/* File: x86/bindivLit16.S */
    /*
     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
     * op1=-1.
     */
    /* div/rem/lit16 vA, vB, #+CCCC */
    /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $-1,%ecx
    jne      .LOP_DIV_INT_LIT16_continue_div
    cmpl     $0x80000000,%eax
    jne      .LOP_DIV_INT_LIT16_continue_div
    movl     $0x80000000,%eax
    jmp      .LOP_DIV_INT_LIT16_finish_div



/* ------------------------------ */
    .balign 64
.L_OP_REM_INT_LIT16: /* 0xd4 */
/* File: x86/OP_REM_INT_LIT16.S */
/* File: x86/bindivLit16.S */
    /*
     * 32-bit binary div/rem operation.  Handles special case of op0=minint and
     * op1=-1.
     */
    /* div/rem/lit16 vA, vB, #+CCCC */
    /* Need A in rINST_FULL, ssssCCCC in ecx, vB in eax */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $-1,%ecx
    jne      .LOP_REM_INT_LIT16_continue_div
    cmpl     $0x80000000,%eax
    jne      .LOP_REM_INT_LIT16_continue_div
    movl     $0,%edx
    jmp      .LOP_REM_INT_LIT16_finish_div



/* ------------------------------ */
    .balign 64
.L_OP_AND_INT_LIT16: /* 0xd5 */
/* File: x86/OP_AND_INT_LIT16.S */
/* File: x86/binopLit16.S */
    /*
     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int/lit16, rsub-int,
     *      and-int/lit16, or-int/lit16, xor-int/lit16
     */
    /* binop/lit16 vA, vB, #+CCCC */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    andl %ecx,%eax                              # for example: addl %ecx, %eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_OR_INT_LIT16: /* 0xd6 */
/* File: x86/OP_OR_INT_LIT16.S */
/* File: x86/binopLit16.S */
    /*
     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int/lit16, rsub-int,
     *      and-int/lit16, or-int/lit16, xor-int/lit16
     */
    /* binop/lit16 vA, vB, #+CCCC */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    orl     %ecx,%eax                              # for example: addl %ecx, %eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_XOR_INT_LIT16: /* 0xd7 */
/* File: x86/OP_XOR_INT_LIT16.S */
/* File: x86/binopLit16.S */
    /*
     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than eax, you can override "result".)
     *
     * For: add-int/lit16, rsub-int,
     *      and-int/lit16, or-int/lit16, xor-int/lit16
     */
    /* binop/lit16 vA, vB, #+CCCC */
    movzbl   rINST_HI,%eax              # eax<- 000000BA
    sarl     $4,%eax                   # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB
    movswl   2(rPC),%ecx                # ecx<- ssssCCCC
    movzbl   rINST_HI,rINST_FULL        # rINST_FULL<- BA
    andb     $0xf,rINST_LO             # rINST_FULL<- A
    xor    %ecx,%eax                              # for example: addl %ecx, %eax
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_ADD_INT_LIT8: /* 0xd8 */
/* File: x86/OP_ADD_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    addl %ecx,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_RSUB_INT_LIT8: /* 0xd9 */
/* File: x86/OP_RSUB_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    subl  %eax,%ecx                             # ex: addl %ecx,%eax
    SET_VREG  (%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_MUL_INT_LIT8: /* 0xda */
/* File: x86/OP_MUL_INT_LIT8.S */
    /* mul/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    SPILL(rPC)
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    imull     %ecx,%eax                # trashes rPC
    UNSPILL(rPC)
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_DIV_INT_LIT8: /* 0xdb */
/* File: x86/OP_DIV_INT_LIT8.S */
/* File: x86/bindivLit8.S */
    /*
     * 32-bit div/rem "lit8" binary operation.  Handles special case of
     * op0=minint & op1=-1
     */
    /* div/rem/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    GET_VREG  (%eax,%eax)              # eax<- rBB
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $0x80000000,%eax
    jne      .LOP_DIV_INT_LIT8_continue_div
    cmpl     $-1,%ecx
    jne      .LOP_DIV_INT_LIT8_continue_div
    movl     $0x80000000,%eax
    jmp      .LOP_DIV_INT_LIT8_finish_div



/* ------------------------------ */
    .balign 64
.L_OP_REM_INT_LIT8: /* 0xdc */
/* File: x86/OP_REM_INT_LIT8.S */
/* File: x86/bindivLit8.S */
    /*
     * 32-bit div/rem "lit8" binary operation.  Handles special case of
     * op0=minint & op1=-1
     */
    /* div/rem/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    GET_VREG  (%eax,%eax)              # eax<- rBB
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    SPILL(rPC)
    cmpl     $0,%ecx
    je       common_errDivideByZero
    cmpl     $0x80000000,%eax
    jne      .LOP_REM_INT_LIT8_continue_div
    cmpl     $-1,%ecx
    jne      .LOP_REM_INT_LIT8_continue_div
    movl     $0,%edx
    jmp      .LOP_REM_INT_LIT8_finish_div



/* ------------------------------ */
    .balign 64
.L_OP_AND_INT_LIT8: /* 0xdd */
/* File: x86/OP_AND_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    andl %ecx,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_OR_INT_LIT8: /* 0xde */
/* File: x86/OP_OR_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    orl     %ecx,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_XOR_INT_LIT8: /* 0xdf */
/* File: x86/OP_XOR_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    xor    %ecx,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHL_INT_LIT8: /* 0xe0 */
/* File: x86/OP_SHL_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    sall  %cl,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SHR_INT_LIT8: /* 0xe1 */
/* File: x86/OP_SHR_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    sarl    %cl,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_USHR_INT_LIT8: /* 0xe2 */
/* File: x86/OP_USHR_INT_LIT8.S */
/* File: x86/binopLit8.S */
    /*
     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
     * that specifies an instruction that performs "result = eax op ecx".
     * This could be an x86 instruction or a function call.  (If the result
     * comes back in a register other than r0, you can override "result".)
     *
     * For: add-int/lit8, rsub-int/lit8
     *      and-int/lit8, or-int/lit8, xor-int/lit8,
     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
     */
    /* binop/lit8 vAA, vBB, #+CC */
    movzbl    2(rPC),%eax              # eax<- BB
    movsbl    3(rPC),%ecx              # ecx<- ssssssCC
    movzx     rINST_HI,rINST_FULL      # rINST_FULL<- AA
    GET_VREG  (%eax,%eax)              # eax<- rBB
    shrl     %cl,%eax                             # ex: addl %ecx,%eax
    SET_VREG  (%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IGET_VOLATILE: /* 0xe3 */
/* File: x86/OP_IGET_VOLATILE.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_VOLATILE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_VOLATILE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IPUT_VOLATILE: /* 0xe4 */
/* File: x86/OP_IPUT_VOLATILE.S */
/* File: x86/OP_IPUT.S */

    /*
     * General 32-bit instance field put.
     *
     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_VOLATILE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_VOLATILE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_SGET_VOLATILE: /* 0xe5 */
/* File: x86/OP_SGET_VOLATILE.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_VOLATILE_resolve                # if not, make it so
.LOP_SGET_VOLATILE_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SPUT_VOLATILE: /* 0xe6 */
/* File: x86/OP_SPUT_VOLATILE.S */
/* File: x86/OP_SPUT.S */
    /*
     * General 32-bit SPUT handler.
     *
     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_VOLATILE_resolve                # if not, make it so
.LOP_SPUT_VOLATILE_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    FETCH_INST_WORD(2)
    movl      %ecx,offStaticField_value(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
/* File: x86/OP_IGET_OBJECT_VOLATILE.S */
/* File: x86/OP_IGET.S */
    /*
     * General 32-bit instance field get.
     *
     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IGET_OBJECT_VOLATILE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)                 # needed by dvmResolveInstField
    GET_GLUE(rIBASE)
    jmp     .LOP_IGET_OBJECT_VOLATILE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
    /* (stub) */
    GET_GLUE(%ecx)
    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
    call      dvmMterp_OP_IGET_WIDE_VOLATILE     # do the real work
    GET_GLUE(%ecx)
    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
    FETCH_INST()
    GOTO_NEXT
/* ------------------------------ */
    .balign 64
.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
    /* (stub) */
    GET_GLUE(%ecx)
    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
    call      dvmMterp_OP_IPUT_WIDE_VOLATILE     # do the real work
    GET_GLUE(%ecx)
    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
    FETCH_INST()
    GOTO_NEXT
/* ------------------------------ */
    .balign 64
.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
    /* (stub) */
    GET_GLUE(%ecx)
    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
    call      dvmMterp_OP_SGET_WIDE_VOLATILE     # do the real work
    GET_GLUE(%ecx)
    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
    FETCH_INST()
    GOTO_NEXT
/* ------------------------------ */
    .balign 64
.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
    /* (stub) */
    GET_GLUE(%ecx)
    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
    call      dvmMterp_OP_SPUT_WIDE_VOLATILE     # do the real work
    GET_GLUE(%ecx)
    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
    FETCH_INST()
    GOTO_NEXT
/* ------------------------------ */
    .balign 64
.L_OP_BREAKPOINT: /* 0xec */
/* File: x86/OP_BREAKPOINT.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
/* File: x86/OP_THROW_VERIFICATION_ERROR.S */
    /*
     * Handle a throw-verification-error instruction.  This throws an
     * exception for an error discovered during verification.  The
     * exception is indicated by AA, with some detail provided by BBBB.
     */
    /* op AA, ref@BBBB */
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                     # eax<- BBBB
    movl     offGlue_method(%ecx),%ecx       # ecx<- glue->method
    EXPORT_PC()
    movzbl   rINST_HI,rINST_FULL             # rINST_FULL<- AA
    movl     %eax,OUT_ARG2(%esp)             # arg2<- BBBB
    movl     rINST_FULL,OUT_ARG1(%esp)       # arg1<- AA
    movl     %ecx,OUT_ARG0(%esp)             # arg0<- method
    SPILL(rPC)
    call     dvmThrowVerificationError       # call(method, kind, ref)
    UNSPILL(rPC)
    jmp      common_exceptionThrown          # handle exception

/* ------------------------------ */
    .balign 64
.L_OP_EXECUTE_INLINE: /* 0xee */
/* File: x86/OP_EXECUTE_INLINE.S */
    /*
     * Execute a "native inline" instruction.
     *
     * We will be calling through a function table:
     *
     * (*gDvmInlineOpsTable[opIndex].func)(arg0, arg1, arg2, arg3, pResult)
     *
     */
    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
    GET_GLUE(%ecx)
    EXPORT_PC()
    movzwl    2(rPC),%eax               # eax<- BBBB
    leal      offGlue_retval(%ecx),%ecx # ecx<- & glue->retval
    movl      %ecx,OUT_ARG4(%esp)
    sarl      $12,rINST_FULL           # rINST_FULL<- arg count (0-4)
    SPILL(rPC)
    call      .LOP_EXECUTE_INLINE_continue      # make call; will return after
    UNSPILL(rPC)
    testl     %eax,%eax                 # successful?
    FETCH_INST_WORD(3)
    je        common_exceptionThrown    # no, handle exception
    ADVANCE_PC(3)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
    /* (stub) */
    GET_GLUE(%ecx)
    SAVE_PC_TO_GLUE(%ecx)            # only need to export these two
    SAVE_FP_TO_GLUE(%ecx)            # only need to export these two
    movl %ecx,OUT_ARG0(%esp)         # glue is first arg to function
    call      dvmMterp_OP_EXECUTE_INLINE_RANGE     # do the real work
    GET_GLUE(%ecx)
    LOAD_PC_FROM_GLUE(%ecx)          # retrieve updated values
    LOAD_FP_FROM_GLUE(%ecx)          # retrieve updated values
    FETCH_INST()
    GOTO_NEXT
/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
/* File: x86/OP_INVOKE_DIRECT_EMPTY.S */
    /*
     * invoke-direct-empty is a no-op in a "standard" interpreter.
     */
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_F1: /* 0xf1 */
/* File: x86/OP_UNUSED_F1.S */
/* File: x86/unused.S */
    jmp     common_abort


/* ------------------------------ */
    .balign 64
.L_OP_IGET_QUICK: /* 0xf2 */
/* File: x86/OP_IGET_QUICK.S */
    /* For: iget-quick, iget-object-quick */
    /* op vA, vB, offset@CCCC */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
    movzwl    2(rPC),%eax               # eax<- field byte offset
    cmpl      $0,%ecx                  # is object null?
    je        common_errNullObject
    movl      (%ecx,%eax,1),%eax
    movzbl    rINST_HI,%ecx
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    andb      $0xf,%cl                 # rINST_FULL<- A
    SET_VREG  (%eax,%ecx)               # fp[A]<- result
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
/* File: x86/OP_IGET_WIDE_QUICK.S */
    /* For: iget-wide-quick */
    /* op vA, vB, offset@CCCC */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
    movzwl    2(rPC),%eax               # eax<- field byte offset
    cmpl      $0,%ecx                  # is object null?
    je        common_errNullObject
    leal      (%ecx,%eax,1),%eax        # eax<- address of 64-bit source
    movl      (%eax),%ecx               # ecx<- lsw
    movl      4(%eax),%eax               # eax<- msw
    movzbl    rINST_HI,rINST_FULL
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    SET_VREG_WORD(%ecx,rINST_FULL,0)    # v[A+0]<- lsw
    SET_VREG_WORD(%eax,rINST_FULL,1)    # v[A+1]<- msw
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
/* File: x86/OP_IGET_OBJECT_QUICK.S */
/* File: x86/OP_IGET_QUICK.S */
    /* For: iget-quick, iget-object-quick */
    /* op vA, vB, offset@CCCC */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
    movzwl    2(rPC),%eax               # eax<- field byte offset
    cmpl      $0,%ecx                  # is object null?
    je        common_errNullObject
    movl      (%ecx,%eax,1),%eax
    movzbl    rINST_HI,%ecx
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    andb      $0xf,%cl                 # rINST_FULL<- A
    SET_VREG  (%eax,%ecx)               # fp[A]<- result
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_IPUT_QUICK: /* 0xf5 */
/* File: x86/OP_IPUT_QUICK.S */
    /* For: iput-quick */
    /* op vA, vB, offset@CCCC */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
    movzbl    rINST_HI,rINST_FULL
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- v[A]
    movzwl    2(rPC),%eax               # eax<- field byte offset
    testl     %ecx,%ecx                  # is object null?
    je        common_errNullObject
    movl      rINST_FULL,(%ecx,%eax,1)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
/* File: x86/OP_IPUT_WIDE_QUICK.S */
    /* For: iput-wide-quick */
    /* op vA, vB, offset@CCCC */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
    movzwl    2(rPC),%eax               # eax<- field byte offset
    testl      %ecx,%ecx                # is object null?
    je        common_errNullObject
    leal      (%ecx,%eax,1),%ecx        # ecx<- Address of 64-bit target
    movzbl    rINST_HI,rINST_FULL
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    GET_VREG_WORD(%eax,rINST_FULL,0)    # eax<- lsw
    GET_VREG_WORD(rINST_FULL,rINST_FULL,1) # rINST_FULL<- msw
    movl      %eax,(%ecx)
    movl      rINST_FULL,4(%ecx)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* ------------------------------ */
    .balign 64
.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
/* File: x86/OP_IPUT_OBJECT_QUICK.S */
    /* For: iput-object-quick */
    /* op vA, vB, offset@CCCC */
    movzbl    rINST_HI,%ecx             # ecx<- BA
    sarl      $4,%ecx                  # ecx<- B
    GET_VREG(%ecx,%ecx)                 # vB (object we're operating on)
    movzbl    rINST_HI,rINST_FULL
    andb      $0xf,rINST_LO            # rINST_FULL<- A
    GET_VREG(rINST_FULL,rINST_FULL)     # rINST_FULL<- v[A]
    movzwl    2(rPC),%eax               # eax<- field byte offset
    testl     %ecx,%ecx                 # is object null?
    je        common_errNullObject
    movl      rINST_FULL,(%ecx,%eax,1)
    GET_GLUE(%eax)
    jmp       .LOP_IPUT_OBJECT_QUICK_finish

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
    /*
     * Handle an optimized virtual method call.
     *
     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
    movzwl    2(rPC),%ecx               # ecx<- BBBB
    .if     (!0)
    andl      $0xf,%eax                # eax<- C (or stays CCCC)
    .endif
    GET_VREG(%eax,%eax)                 # eax<- vC ("this" ptr)
    testl     %eax,%eax                 # null?
    je        common_errNullObject      # yep, throw exception
    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
    EXPORT_PC()                         # might throw later - get ready
    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
    jmp       common_invokeMethodNoRange

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
/* File: x86/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
/* File: x86/OP_INVOKE_VIRTUAL_QUICK.S */
    /*
     * Handle an optimized virtual method call.
     *
     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    movzwl    4(rPC),%eax               # eax<- FEDC or CCCC
    movzwl    2(rPC),%ecx               # ecx<- BBBB
    .if     (!1)
    andl      $0xf,%eax                # eax<- C (or stays CCCC)
    .endif
    GET_VREG(%eax,%eax)                 # eax<- vC ("this" ptr)
    testl     %eax,%eax                 # null?
    je        common_errNullObject      # yep, throw exception
    movl      offObject_clazz(%eax),%eax # eax<- thisPtr->clazz
    movl      offClassObject_vtable(%eax),%eax # eax<- thisPtr->clazz->vtable
    EXPORT_PC()                         # might throw later - get ready
    movl      (%eax,%ecx,4),%eax        # eax<- vtable[BBBB]
    jmp       common_invokeMethodRange


/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
/* File: x86/OP_INVOKE_SUPER_QUICK.S */
    /*
     * Handle an optimized "super" method call.
     *
     * for: [opt] invoke-super-quick, invoke-super-quick/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%ecx)
    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
    movl      offGlue_method(%ecx),%ecx # ecx<- current method
    .if       (!0)
    andl      $0xf,%eax                # eax<- D (or stays CCCC)
    .endif
    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
    GET_VREG(%eax,%eax)                 # eax<- "this"
    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
    testl     %eax,%eax                 # null "this"?
    je        common_errNullObject      # "this" is null, throw exception
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
    EXPORT_PC()
    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
    jmp       common_invokeMethodNoRange

/* ------------------------------ */
    .balign 64
.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
/* File: x86/OP_INVOKE_SUPER_QUICK_RANGE.S */
/* File: x86/OP_INVOKE_SUPER_QUICK.S */
    /*
     * Handle an optimized "super" method call.
     *
     * for: [opt] invoke-super-quick, invoke-super-quick/range
     */
    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
    GET_GLUE(%ecx)
    movzwl    4(rPC),%eax               # eax<- GFED or CCCC
    movl      offGlue_method(%ecx),%ecx # ecx<- current method
    .if       (!1)
    andl      $0xf,%eax                # eax<- D (or stays CCCC)
    .endif
    movl      offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
    GET_VREG(%eax,%eax)                 # eax<- "this"
    movl      offClassObject_super(%ecx),%ecx # ecx<- method->clazz->super
    testl     %eax,%eax                 # null "this"?
    je        common_errNullObject      # "this" is null, throw exception
    movzwl    2(rPC),%eax               # eax<- BBBB
    movl      offClassObject_vtable(%ecx),%ecx # ecx<- vtable
    EXPORT_PC()
    movl      (%ecx,%eax,4),%eax        # eax<- super->vtable[BBBB]
    jmp       common_invokeMethodRange


/* ------------------------------ */
    .balign 64
.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
/* File: x86/OP_IPUT_OBJECT_VOLATILE.S */
/* File: x86/OP_IPUT_OBJECT.S */
    /*
     * Object field put.
     *
     * for: iput-object
     */
    /* op vA, vB, field@CCCC */
    GET_GLUE(%ecx)
    SPILL(rIBASE)                                 # need another reg
    movzwl  2(rPC),rIBASE                         # rIBASE<- 0000CCCC
    movl    offGlue_methodClassDex(%ecx),%eax     # eax<- DvmDex
    movzbl  rINST_HI,%ecx                         # ecx<- BA
    sarl    $4,%ecx                              # ecx<- B
    movl    offDvmDex_pResFields(%eax),%eax       # eax<- pDvmDex->pResFields
    movzbl  rINST_HI,rINST_FULL                   # rINST_FULL<- BA
    andb    $0xf,rINST_LO                        # rINST_FULL<- A
    GET_VREG(%ecx,%ecx)                           # ecx<- fp[B], the object ptr
    movl    (%eax,rIBASE,4),%eax                  # resolved entry
    testl   %eax,%eax                             # is resolved entry null?
    jne     .LOP_IPUT_OBJECT_VOLATILE_finish                    # no, already resolved
    movl    rIBASE,OUT_ARG1(%esp)
    GET_GLUE(rIBASE)
    jmp     .LOP_IPUT_OBJECT_VOLATILE_resolve


/* ------------------------------ */
    .balign 64
.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
/* File: x86/OP_SGET_OBJECT_VOLATILE.S */
/* File: x86/OP_SGET.S */
    /*
     * General 32-bit SGET handler.
     *
     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField ptr
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SGET_OBJECT_VOLATILE_resolve                # if not, make it so
.LOP_SGET_OBJECT_VOLATILE_finish:     # field ptr in eax
    movl      offStaticField_value(%eax),%eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)
    GOTO_NEXT


/* ------------------------------ */
    .balign 64
.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
/* File: x86/OP_SPUT_OBJECT_VOLATILE.S */
/* File: x86/OP_SPUT_OBJECT.S */
    /*
     * SPUT object handler.
     */
    /* op vAA, field@BBBB */
    GET_GLUE(%ecx)
    movzwl    2(rPC),%eax                        # eax<- field ref BBBB
    movl      offGlue_methodClassDex(%ecx),%ecx  # ecx<- DvmDex
    movl      offDvmDex_pResFields(%ecx),%ecx    # ecx<- dvmDex->pResFields
    movl      (%ecx,%eax,4),%eax                 # eax<- resolved StaticField
    testl     %eax,%eax                          # resolved entry null?
    je        .LOP_SPUT_OBJECT_VOLATILE_resolve                # if not, make it so
.LOP_SPUT_OBJECT_VOLATILE_finish:     # field ptr in eax
    movzbl    rINST_HI,%ecx                      # ecx<- AA
    GET_VREG(%ecx,%ecx)
    jmp       .LOP_SPUT_OBJECT_VOLATILE_continue


/* ------------------------------ */
    .balign 64
.L_OP_UNUSED_FF: /* 0xff */
/* File: x86/OP_UNUSED_FF.S */
/* File: x86/unused.S */
    jmp     common_abort



    .balign 64
    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
    .global dvmAsmInstructionEnd
dvmAsmInstructionEnd:

/*
 * ===========================================================================
 *  Sister implementations
 * ===========================================================================
 */
    .global dvmAsmSisterStart
    .type   dvmAsmSisterStart, %function
    .text
    .balign 4
dvmAsmSisterStart:

/* continuation for OP_CONST_STRING */

/* This is the less common path, so we'll redo some work
   here rather than force spills on the common path */
.LOP_CONST_STRING_resolve:
    GET_GLUE(%eax)
    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
    EXPORT_PC()
    movl     offGlue_method(%eax),%eax # eax<- glue->method
    movzwl   2(rPC),%ecx               # ecx<- BBBB
    movl     offMethod_clazz(%eax),%eax
    SPILL(rPC)
    movl     %ecx,OUT_ARG1(%esp)
    movl     %eax,OUT_ARG0(%esp)
    call     dvmResolveString          # go resolve
    UNSPILL(rPC)
    testl    %eax,%eax                 # failed?
    je       common_exceptionThrown
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_CONST_STRING_JUMBO */

/* This is the less common path, so we'll redo some work
   here rather than force spills on the common path */
.LOP_CONST_STRING_JUMBO_resolve:
    GET_GLUE(%eax)
    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
    EXPORT_PC()
    movl     offGlue_method(%eax),%eax # eax<- glue->method
    movl     2(rPC),%ecx               # ecx<- BBBBBBBB
    movl     offMethod_clazz(%eax),%eax
    SPILL(rPC)
    movl     %ecx,OUT_ARG1(%esp)
    movl     %eax,OUT_ARG0(%esp)
    call     dvmResolveString          # go resolve
    UNSPILL(rPC)
    testl    %eax,%eax                 # failed?
    je       common_exceptionThrown
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    GOTO_NEXT

/* continuation for OP_CONST_CLASS */

/* This is the less common path, so we'll redo some work
   here rather than force spills on the common path */
.LOP_CONST_CLASS_resolve:
    GET_GLUE(%eax)
    movl     %ecx,rINST_FULL           # rINST_FULL<- AA
    EXPORT_PC()
    movl     offGlue_method(%eax),%eax # eax<- glue->method
    movl     $1,OUT_ARG2(%esp)        # true
    movzwl   2(rPC),%ecx               # ecx<- BBBB
    movl     offMethod_clazz(%eax),%eax
    SPILL(rPC)
    movl     %ecx,OUT_ARG1(%esp)
    movl     %eax,OUT_ARG0(%esp)
    call     dvmResolveClass           # go resolve
    UNSPILL(rPC)
    testl    %eax,%eax                 # failed?
    je       common_exceptionThrown
    SET_VREG(%eax,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_MONITOR_ENTER */

.LOP_MONITOR_ENTER_continue:
    SPILL(rPC)                          # have to - caller save
    movl    %ecx,OUT_ARG0(%esp)
    movl    %eax,OUT_ARG1(%esp)
    call    dvmLockObject               # dvmLockObject(self,object)
    UNSPILL(rPC)
#ifdef WITH_DEADLOCK_PREDICTION
    GET_GLUE(%ecx)
    movl    offGlueSelf(%ecx),%ecx      # ecx<- glue->self
    movl    offThread_exception(%ecx),%eax
    testl   %eax,%eax
    jne     common_exceptionThrown
#endif
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_MONITOR_EXIT */

.LOP_MONITOR_EXIT_continue:
    call    dvmUnlockObject             # unlock(self,obj)
    UNSPILL(rPC)
    FETCH_INST_WORD(1)
    testl   %eax,%eax                   # success?
    ADVANCE_PC(1)
    je      common_exceptionThrown      # no, exception pending
    GOTO_NEXT
.LOP_MONITOR_EXIT_errNullObject:
    ADVANCE_PC(1)                       # advance before throw
    jmp     common_errNullObject

/* continuation for OP_CHECK_CAST */

    /*
     * Trivial test failed, need to perform full check.  This is common.
     *  ecx holds obj->clazz
     *  eax holds class resolved from BBBB
     *  rINST_FULL holds object
     */
.LOP_CHECK_CAST_fullcheck:
    movl    %eax,OUT_ARG1(%esp)
    movl    %ecx,OUT_ARG0(%esp)
    SPILL(rPC)
    call    dvmInstanceofNonTrivial     # eax<- boolean result
    UNSPILL(rPC)
    testl   %eax,%eax                   # failed?
    jne     .LOP_CHECK_CAST_okay            # no, success

    # A cast has failed.  We need to throw a ClassCastException with the
    # class of the object that failed to be cast.
    EXPORT_PC()
    movl    offObject_clazz(rINST_FULL),%ecx  # ecx<- obj->clazz
    movl    $.LstrClassCastException,%eax
    movl    offClassObject_descriptor(%ecx),%ecx
    movl    %eax,OUT_ARG0(%esp)     # arg0<- message
    movl    %ecx,OUT_ARG1(%esp)     # arg1<- obj->clazz->descriptor
    SPILL(rPC)
    call    dvmThrowExceptionWithClassMessage
    UNSPILL(rPC)
    jmp     common_exceptionThrown

    /*
     * Resolution required.  This is the least-likely path, and we're
     * going to have to recreate some data.
     *
     *  rINST_FULL holds object
     */
.LOP_CHECK_CAST_resolve:
    GET_GLUE(%ecx)
    EXPORT_PC()
    movzwl  2(rPC),%eax                # eax<- BBBB
    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
    movl    %eax,OUT_ARG1(%esp)        # arg1<- BBBB
    movl    offMethod_clazz(%ecx),%ecx # ecx<- metho->clazz
    movl    $0,OUT_ARG2(%esp)         # arg2<- false
    movl    %ecx,OUT_ARG0(%esp)        # arg0<- method->clazz
    SPILL(rPC)
    call    dvmResolveClass            # eax<- resolved ClassObject ptr
    UNSPILL(rPC)
    testl   %eax,%eax                  # got null?
    je      common_exceptionThrown     # yes, handle exception
    movl    offObject_clazz(rINST_FULL),%ecx  # ecx<- obj->clazz
    jmp     .LOP_CHECK_CAST_resolved       # pick up where we left off

/* continuation for OP_INSTANCE_OF */

    /*
     * Trivial test failed, need to perform full check.  This is common.
     *  eax holds obj->clazz
     *  ecx holds class resolved from BBBB
     *  rINST_HI has BA
     *  rPC already spilled
     */
.LOP_INSTANCE_OF_fullcheck:
    movl    %eax,OUT_ARG0(%esp)
    movl    %ecx,OUT_ARG1(%esp)
    call    dvmInstanceofNonTrivial     # eax<- boolean result
    # fall through to OP_INSTANCE_OF_store

    /*
     * eax holds boolean result
     * rINST_HI holds BA
     */
.LOP_INSTANCE_OF_store:
    UNSPILL(rPC)
    movzbl  rINST_HI,%ecx               # ecx<- BA
    FETCH_INST_WORD(2)
    andb    $0xf,%cl                   # ecl<- A
    ADVANCE_PC(2)
    SET_VREG(%eax,%ecx)                 # vA<- eax
    GOTO_NEXT

    /*
     * Trivial test succeeded, save and bail.
     *  r9 holds A
     */
.LOP_INSTANCE_OF_trivial:
    UNSPILL(rPC)
    movzbl  rINST_HI,%ecx               # ecx<- BA
    FETCH_INST_WORD(2)
    andb    $0xf,%cl                   # ecl<- A
    ADVANCE_PC(2)
    movl    $1,%eax
    SET_VREG(%eax,%ecx)                  # vA<- true
    GOTO_NEXT

    /*
     * Resolution required.  This is the least-likely path.
     *
     *  rPC holds BBBB
     *  rINST_HI holds BA
     */
.LOP_INSTANCE_OF_resolve:
    movl    rPC,OUT_ARG1(%esp)          # arg1<- BBBB
    GET_GLUE(%ecx)
    UNSPILL(rPC)
    movl    offGlue_method(%ecx),%ecx
    movl    $1,OUT_ARG2(%esp)          # arg2<- true
    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
    EXPORT_PC()
    movl    %ecx,OUT_ARG0(%esp)         # arg0<- method->clazz
    call    dvmResolveClass             # eax<- resolved ClassObject ptr
    UNSPILL(rPC)
    testl   %eax,%eax                   # success?
    je      common_exceptionThrown      # no, handle exception
/* Now, we need to sync up with fast path.  We need eax to
 * hold the obj->clazz, and ecx to hold the resolved class
 */
    movl    %eax,%ecx                   # ecx<- resolved class
    movzbl  rINST_HI,%eax               # eax<- BA
    sarl    $4,%eax                    # eax<- B
    GET_VREG(%eax,%eax)                 # eax<- vB (obj)
    movl    offObject_clazz(%eax),%eax  # eax<- obj->clazz
    jmp     .LOP_INSTANCE_OF_resolved

/* continuation for OP_NEW_INSTANCE */

.LOP_NEW_INSTANCE_initialized:  # on entry, ecx<- class
    /* TODO: remove test for interface/abstract, now done in verifier */
    testl     $(ACC_INTERFACE|ACC_ABSTRACT),offClassObject_accessFlags(%ecx)
    movl      $ALLOC_DONT_TRACK,OUT_ARG1(%esp)
    jne       .LOP_NEW_INSTANCE_abstract
.LOP_NEW_INSTANCE_finish: # ecx=class
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmAllocObject             # eax<- new object
    UNSPILL(rPC)
    movl     rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    testl    %eax,%eax                  # success?
    je       common_exceptionThrown     # no, bail out
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT

    /*
     * Class initialization required.
     *
     *  ecx holds class object
     */
.LOP_NEW_INSTANCE_needinit:
    SPILL_TMP(%ecx)                     # save object
    movl    %ecx,OUT_ARG0(%esp)
    call    dvmInitClass                # initialize class
    UNSPILL_TMP(%ecx)                   # restore object
    testl   %eax,%eax                   # success?
    jne     .LOP_NEW_INSTANCE_initialized     # success, continue
    UNSPILL(rPC)                        # failed, restore PC
    jmp     common_exceptionThrown      # go deal with init exception

    /*
     * Resolution required.  This is the least-likely path.
     *
     */
.LOP_NEW_INSTANCE_resolve:
    GET_GLUE(%ecx)
    movzwl  2(rPC),%eax
    movl    offGlue_method(%ecx),%ecx   # ecx<- glue->method
    movl    %eax,OUT_ARG1(%esp)
    movl    offMethod_clazz(%ecx),%ecx  # ecx<- method->clazz
    movl    $0,OUT_ARG2(%esp)
    movl    %ecx,OUT_ARG0(%esp)
    call    dvmResolveClass             # call(clazz,off,flags)
    movl    %eax,%ecx                   # ecx<- resolved ClassObject ptr
    testl   %ecx,%ecx                   # success?
    jne     .LOP_NEW_INSTANCE_resolved        # good to go
    UNSPILL(rPC)
    jmp     common_exceptionThrown      # no, handle exception

    /*
     * TODO: remove this
     * We can't instantiate an abstract class or interface, so throw an
     * InstantiationError with the class descriptor as the message.
     *
     *  ecx holds class object
     */
.LOP_NEW_INSTANCE_abstract:
    movl    offClassObject_descriptor(%ecx),%eax
    movl    $.LstrInstantiationError,OUT_ARG0(%esp)
    movl    %eax,OUT_ARG1(%esp)
    call    dvmThrowExceptionWithClassMessage
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/* continuation for OP_NEW_ARRAY */

    /*
     * Resolve class.  (This is an uncommon case.)
     *  ecx holds class (null here)
     *  eax holds array length (vB)
     */
.LOP_NEW_ARRAY_resolve:
    GET_GLUE(%ecx)
    SPILL_TMP(%eax)                    # save array length
    movl    offGlue_method(%ecx),%ecx  # ecx<- glue->method
    movzwl  2(rPC),%eax                # eax<- CCCC
    movl    offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
    movl    %eax,OUT_ARG1(%esp)
    movl    $0,OUT_ARG2(%esp)
    movl    %ecx,OUT_ARG0(%esp)
    SPILL(rPC)
    call    dvmResolveClass            # eax<- call(clazz,ref,flag)
    UNSPILL(rPC)
    movl    %eax,%ecx
    UNSPILL_TMP(%eax)
    testl   %ecx,%ecx                  # successful resolution?
    je      common_exceptionThrown     # no, bail.
# fall through to OP_NEW_ARRAY_finish

    /*
     * Finish allocation
     *
     * ecx holds class
     * eax holds array length (vB)
     */
.LOP_NEW_ARRAY_finish:
    movl    %ecx,OUT_ARG0(%esp)
    movl    %eax,OUT_ARG1(%esp)
    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)
    SPILL(rPC)
    call    dvmAllocArrayByClass    # eax<- call(clazz,length,flags)
    UNSPILL(rPC)
    testl   %eax,%eax               # failed?
    je      common_exceptionThrown  # yup - go handle
    movl    rINST_FULL,%ecx
    FETCH_INST_WORD(2)
    SET_VREG(%eax,%ecx)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_FILLED_NEW_ARRAY */

.LOP_FILLED_NEW_ARRAY_more:
    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
    UNSPILL(rPC)
    testl   %eax,%eax                         # null?
    je      common_exceptionThrown            # yes, handle it

       # note: fall through to .LOP_FILLED_NEW_ARRAY_continue

    /*
     * On entry:
     *    eax holds array class [r0]
     *    rINST_FULL holds AA or BB [r10]
     *    ecx is scratch
     *    rPC is valid, but has been spilled
     */
.LOP_FILLED_NEW_ARRAY_continue:
    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
    GET_GLUE(%eax)
    cmpb    $'I',%cl                             # supported?
    je      1f
    cmpb    $'L',%cl
    je      1f
    cmpb    $'[',%cl
    jne      .LOP_FILLED_NEW_ARRAY_notimpl                  # no, not handled yet
1:
    movl    %ecx,offGlue_retval+4(%eax)           # save type
    .if      (!0)
    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
    sarl    $4,rINST_FULL
    .endif
    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
    UNSPILL(rPC)
    GET_GLUE(%ecx)
    testl   %eax,%eax                             # alloc successful?
    je      common_exceptionThrown                # no, handle exception
    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents

/* at this point:
 *     eax is pointer to tgt
 *     rINST_FULL is length
 *     ecx is FEDC or CCCC
 *     TMP_SPILL is BA
 *     rPC is valid, but spilled
 *  We now need to copy values from registers into the array
 */

    .if 0
    # set up src pointer
    SPILL(rFP)     # esi
    SPILL(rIBASE)   # edi
    movl    %eax,%edi         # set up dst ptr
    leal    (rFP,%ecx,4),%esi # set up src ptr
    movl    rINST_FULL,%ecx   # load count register
    FETCH_INST_WORD(3)
    rep
    movsd
    GET_GLUE(%ecx)
    UNSPILL(rIBASE)
    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
    UNSPILL(rFP)
    .else
    testl  rINST_FULL,rINST_FULL
    je     4f
    UNSPILL_TMP(rPC)
    andl   $0x0f,rPC            # rPC<- 0000000A
    sall   $16,rPC              # rPC<- 000A0000
    orl    %ecx,rPC              # rpc<- 000AFEDC
3:
    movl   $0xf,%ecx
    andl   rPC,%ecx           # ecx<- next reg to load
    GET_VREG(%ecx,%ecx)
    shrl   $4,rPC
    leal   4(%eax),%eax
    movl   %ecx,-4(%eax)
    sub    $1,rINST_FULL
    jne    3b
4:
    GET_GLUE(%ecx)
    UNSPILL(rPC)
    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
    FETCH_INST_WORD(3)
    .endif

    cmpb    $'I',%al                        # Int array?
    je      5f                               # skip card mark if so
    movl    offGlue_retval(%ecx),%eax        # eax<- object head
    movl    offGlue_cardTable(%ecx),%ecx     # card table base
    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
    movb    %cl,(%ecx,%eax)                  # mark card based on object head
5:
    ADVANCE_PC(3)
    GOTO_NEXT


    /*
     * Throw an exception indicating that we have not implemented this
     * mode of filled-new-array.
     */
.LOP_FILLED_NEW_ARRAY_notimpl:
    movl    $.LstrInternalError,%eax
    movl    %eax,OUT_ARG0(%esp)
    movl    $.LstrFilledNewArrayNotImpl,%eax
    movl    %eax,OUT_ARG1(%esp)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/* continuation for OP_FILLED_NEW_ARRAY_RANGE */

.LOP_FILLED_NEW_ARRAY_RANGE_more:
    movl    offMethod_clazz(%eax),%eax        # eax<- method->clazz
    movl    %eax,OUT_ARG0(%esp)               # arg0<- clazz
    call    dvmResolveClass                   # eax<- call(clazz,ref,flag)
    UNSPILL(rPC)
    testl   %eax,%eax                         # null?
    je      common_exceptionThrown            # yes, handle it

       # note: fall through to .LOP_FILLED_NEW_ARRAY_RANGE_continue

    /*
     * On entry:
     *    eax holds array class [r0]
     *    rINST_FULL holds AA or BB [r10]
     *    ecx is scratch
     *    rPC is valid, but has been spilled
     */
.LOP_FILLED_NEW_ARRAY_RANGE_continue:
    movl    offClassObject_descriptor(%eax),%ecx  # ecx<- arrayClass->descriptor
    movl    $ALLOC_DONT_TRACK,OUT_ARG2(%esp)     # arg2<- flags
    movzbl  1(%ecx),%ecx                          # ecx<- descriptor[1]
    movl    %eax,OUT_ARG0(%esp)                   # arg0<- arrayClass
    GET_GLUE(%eax)
    cmpb    $'I',%cl                             # supported?
    je      1f
    cmpb    $'L',%cl
    je      1f
    cmpb    $'[',%cl
    jne      .LOP_FILLED_NEW_ARRAY_RANGE_notimpl                  # no, not handled yet
1:
    movl    %ecx,offGlue_retval+4(%eax)           # save type
    .if      (!1)
    SPILL_TMP(rINST_FULL)                         # save copy, need "B" later
    sarl    $4,rINST_FULL
    .endif
    movl    rINST_FULL,OUT_ARG1(%esp)             # arg1<- A or AA (length)
    call    dvmAllocArrayByClass                  # eax<- call(arrayClass, length, flags)
    UNSPILL(rPC)
    GET_GLUE(%ecx)
    testl   %eax,%eax                             # alloc successful?
    je      common_exceptionThrown                # no, handle exception
    movl    %eax,offGlue_retval(%ecx)             # retval.l<- new array
    movzwl  4(rPC),%ecx                           # ecx<- FEDC or CCCC
    leal    offArrayObject_contents(%eax),%eax    # eax<- newArray->contents

/* at this point:
 *     eax is pointer to tgt
 *     rINST_FULL is length
 *     ecx is FEDC or CCCC
 *     TMP_SPILL is BA
 *     rPC is valid, but spilled
 *  We now need to copy values from registers into the array
 */

    .if 1
    # set up src pointer
    SPILL(rFP)     # esi
    SPILL(rIBASE)   # edi
    movl    %eax,%edi         # set up dst ptr
    leal    (rFP,%ecx,4),%esi # set up src ptr
    movl    rINST_FULL,%ecx   # load count register
    FETCH_INST_WORD(3)
    rep
    movsd
    GET_GLUE(%ecx)
    UNSPILL(rIBASE)
    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
    UNSPILL(rFP)
    .else
    testl  rINST_FULL,rINST_FULL
    je     4f
    UNSPILL_TMP(rPC)
    andl   $0x0f,rPC            # rPC<- 0000000A
    sall   $16,rPC              # rPC<- 000A0000
    orl    %ecx,rPC              # rpc<- 000AFEDC
3:
    movl   $0xf,%ecx
    andl   rPC,%ecx           # ecx<- next reg to load
    GET_VREG(%ecx,%ecx)
    shrl   $4,rPC
    leal   4(%eax),%eax
    movl   %ecx,-4(%eax)
    sub    $1,rINST_FULL
    jne    3b
4:
    GET_GLUE(%ecx)
    UNSPILL(rPC)
    movl    offGlue_retval+4(%ecx),%eax      # eax<- type
    FETCH_INST_WORD(3)
    .endif

    cmpb    $'I',%al                        # Int array?
    je      5f                               # skip card mark if so
    movl    offGlue_retval(%ecx),%eax        # eax<- object head
    movl    offGlue_cardTable(%ecx),%ecx     # card table base
    shrl    $GC_CARD_SHIFT,%eax             # convert to card num
    movb    %cl,(%ecx,%eax)                  # mark card based on object head
5:
    ADVANCE_PC(3)
    GOTO_NEXT


    /*
     * Throw an exception indicating that we have not implemented this
     * mode of filled-new-array.
     */
.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
    movl    $.LstrInternalError,%eax
    movl    %eax,OUT_ARG0(%esp)
    movl    $.LstrFilledNewArrayNotImpl,%eax
    movl    %eax,OUT_ARG1(%esp)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/* continuation for OP_CMPL_FLOAT */

.LOP_CMPL_FLOAT_isNaN:
    movl      $-1,%ecx
    jmp       .LOP_CMPL_FLOAT_finish

/* continuation for OP_CMPG_FLOAT */

.LOP_CMPG_FLOAT_isNaN:
    movl      $1,%ecx
    jmp       .LOP_CMPG_FLOAT_finish

/* continuation for OP_CMPL_DOUBLE */

.LOP_CMPL_DOUBLE_isNaN:
    movl      $-1,%ecx
    jmp       .LOP_CMPL_DOUBLE_finish

/* continuation for OP_CMPG_DOUBLE */

.LOP_CMPG_DOUBLE_isNaN:
    movl      $1,%ecx
    jmp       .LOP_CMPG_DOUBLE_finish

/* continuation for OP_CMP_LONG */

.LOP_CMP_LONG_bigger:
    UNSPILL(rPC)
    movl      $1,%ecx
    jmp       .LOP_CMP_LONG_finish
.LOP_CMP_LONG_smaller:
    UNSPILL(rPC)
    movl      $-1,%ecx
.LOP_CMP_LONG_finish:
    SET_VREG(%ecx,rINST_FULL)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_AGET_WIDE */

.LOP_AGET_WIDE_finish:
    leal      offArrayObject_contents(%eax,%ecx,8),%eax
    movl      (%eax),%ecx
    movl      4(%eax),%eax
    SET_VREG_WORD(%ecx,rINST_FULL,0)
    SET_VREG_WORD(%eax,rINST_FULL,1)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_APUT_WIDE */

.LOP_APUT_WIDE_finish:
    leal      offArrayObject_contents(%eax,%ecx,8),%eax
    GET_VREG_WORD(%ecx,rINST_FULL,0)
    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)
    movl      rINST_FULL,4(%eax)
    FETCH_INST_WORD(2)
    movl      %ecx,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_APUT_OBJECT */

    /* On entry:
     *   eax<- array object
     *   ecx<- index
     *   rINST_FULL<- vAA
     */
.LOP_APUT_OBJECT_continue:
    leal      offArrayObject_contents(%eax,%ecx,4),%ecx
    testl     rINST_FULL,rINST_FULL     # storing null reference?
    je        .LOP_APUT_OBJECT_skip_check
    SPILL(rPC)
    SPILL_TMP(%ecx)
    movl      %eax,LOCAL0_OFFSET(%ebp)   # save copy of object head
    movl      offObject_clazz(%eax),%eax # eax<- arrayObj->clazz
    movl      offObject_clazz(rINST_FULL),%ecx # ecx<- obj->clazz
    movl      %eax,OUT_ARG1(%esp)
    movl      %ecx,OUT_ARG0(%esp)
    call      dvmCanPutArrayElement     # test object type vs. array type
    UNSPILL(rPC)
    UNSPILL_TMP(%ecx)
    testl     %eax,%eax
    GET_GLUE(%eax)
    je        common_errArrayStore
    movl      offGlue_cardTable(%eax),%eax   # get card table base
    movl      rINST_FULL,(%ecx)
    movl      LOCAL0_OFFSET(%ebp),%ecx       # recover object head
    FETCH_INST_WORD(2)
    shrl      $GC_CARD_SHIFT,%ecx           # object head to card number
    movb      %al,(%eax,%ecx)                # mark card using object head
    ADVANCE_PC(2)
    GOTO_NEXT

.LOP_APUT_OBJECT_skip_check:
    movl      rINST_FULL,(%ecx)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET */


.LOP_IGET_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_finish
    jmp     common_exceptionThrown

.LOP_IGET_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_WIDE */


.LOP_IGET_WIDE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_WIDE_finish
    jmp     common_exceptionThrown

.LOP_IGET_WIDE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
    movl    (%eax),%ecx                          # ecx<- lsw
    movl    4(%eax),%eax                         # eax<- msw
    SET_VREG_WORD(%ecx,rINST_FULL,0)
    SET_VREG_WORD(%eax,rINST_FULL,1)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_OBJECT */


.LOP_IGET_OBJECT_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_OBJECT_finish
    jmp     common_exceptionThrown

.LOP_IGET_OBJECT_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_BOOLEAN */


.LOP_IGET_BOOLEAN_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_BOOLEAN_finish
    jmp     common_exceptionThrown

.LOP_IGET_BOOLEAN_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movzbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_BYTE */


.LOP_IGET_BYTE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_BYTE_finish
    jmp     common_exceptionThrown

.LOP_IGET_BYTE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movsbl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_CHAR */


.LOP_IGET_CHAR_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_CHAR_finish
    jmp     common_exceptionThrown

.LOP_IGET_CHAR_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movzwl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_SHORT */


.LOP_IGET_SHORT_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_SHORT_finish
    jmp     common_exceptionThrown

.LOP_IGET_SHORT_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movswl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT */


.LOP_IPUT_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_finish
    jmp     common_exceptionThrown

.LOP_IPUT_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_WIDE */


.LOP_IPUT_WIDE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_WIDE_finish
    jmp     common_exceptionThrown

.LOP_IPUT_WIDE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    leal    (%ecx,%eax,1),%eax                   # eax<- address of field
    GET_VREG_WORD(%ecx,rINST_FULL,0)             # ecx<- lsw
    GET_VREG_WORD(rINST_FULL,rINST_FULL,1)       # rINST_FULL<- msw
    movl    rINST_FULL,4(%eax)
    FETCH_INST_WORD(2)
    movl    %ecx,(%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_OBJECT */


.LOP_IPUT_OBJECT_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_OBJECT_finish
    jmp     common_exceptionThrown

.LOP_IPUT_OBJECT_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl    rINST_FULL,(%ecx,%eax)          # obj.field <- v[A](8/16/32 bits)
    GET_GLUE(%eax)
    testl   rINST_FULL,rINST_FULL                # stored a NULL?
    movl    offGlue_cardTable(%eax),%eax         # get card table base
    FETCH_INST_WORD(2)
    je      1f                                   # skip card mark if null store
    shrl    $GC_CARD_SHIFT,%ecx                 # object head to card number
    movb    %al,(%eax,%ecx)                      # mark card using object head
1:
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_BOOLEAN */


.LOP_IPUT_BOOLEAN_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_BOOLEAN_finish
    jmp     common_exceptionThrown

.LOP_IPUT_BOOLEAN_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_BYTE */


.LOP_IPUT_BYTE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_BYTE_finish
    jmp     common_exceptionThrown

.LOP_IPUT_BYTE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movb   rINST_LO,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_CHAR */


.LOP_IPUT_CHAR_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_CHAR_finish
    jmp     common_exceptionThrown

.LOP_IPUT_CHAR_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_SHORT */


.LOP_IPUT_SHORT_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_SHORT_finish
    jmp     common_exceptionThrown

.LOP_IPUT_SHORT_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movw   rINST,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_SGET */

    /*
     * Go resolve the field
     */
.LOP_SGET_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SGET_WIDE */

    /*
     * Go resolve the field
     */
.LOP_SGET_WIDE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_WIDE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SGET_OBJECT */

    /*
     * Go resolve the field
     */
.LOP_SGET_OBJECT_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_OBJECT_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SGET_BOOLEAN */

    /*
     * Go resolve the field
     */
.LOP_SGET_BOOLEAN_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_BOOLEAN_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SGET_BYTE */

    /*
     * Go resolve the field
     */
.LOP_SGET_BYTE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_BYTE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SGET_CHAR */

    /*
     * Go resolve the field
     */
.LOP_SGET_CHAR_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_CHAR_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SGET_SHORT */

    /*
     * Go resolve the field
     */
.LOP_SGET_SHORT_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_SHORT_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT */

    /*
     * Go resolve the field
     */
.LOP_SPUT_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_WIDE */

    /*
     * Go resolve the field
     */
.LOP_SPUT_WIDE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_WIDE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_OBJECT */


.LOP_SPUT_OBJECT_continue:
    movl      %ecx,offStaticField_value(%eax)    # do the store
    testl     %ecx,%ecx                          # stored null object ptr?
    FETCH_INST_WORD(2)
    je        1f                                 # skip card mark if null
    GET_GLUE(%ecx)
    movl      offField_clazz(%eax),%eax          # eax<- field->clazz
    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
    shrl      $GC_CARD_SHIFT,%eax               # head to card number
    movb      %cl,(%ecx,%eax)                    # mark card
1:
    ADVANCE_PC(2)
    GOTO_NEXT

.LOP_SPUT_OBJECT_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_OBJECT_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_BOOLEAN */

    /*
     * Go resolve the field
     */
.LOP_SPUT_BOOLEAN_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_BOOLEAN_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_BYTE */

    /*
     * Go resolve the field
     */
.LOP_SPUT_BYTE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_BYTE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_CHAR */

    /*
     * Go resolve the field
     */
.LOP_SPUT_CHAR_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_CHAR_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_SHORT */

    /*
     * Go resolve the field
     */
.LOP_SPUT_SHORT_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_SHORT_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_INVOKE_VIRTUAL */


.LOP_INVOKE_VIRTUAL_more:
    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
    UNSPILL(rPC)
    testl     %eax,%eax                   # got null?
    jne       .LOP_INVOKE_VIRTUAL_continue        # no, continue
    jmp       common_exceptionThrown      # yes, handle exception

    /* At this point:
     *   eax = resolved base method
     *   ecx = scratch
     */
.LOP_INVOKE_VIRTUAL_continue:
    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
    .if       (!0)
    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
    .endif
    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
    testl     %ecx,%ecx                 # null this?
    je        common_errNullObject      # go if so
    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
    jmp       common_invokeMethodNoRange

/* continuation for OP_INVOKE_SUPER */

    /*
     * At this point:
     *  ecx = resolved base method [r0]
     *  eax = method->clazz [r9]
     */
.LOP_INVOKE_SUPER_continue:
    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
    jae     .LOP_INVOKE_SUPER_nsm           # method not present in superclass
    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
    jmp     common_invokeMethodNoRange


    /* At this point:
     * ecx = null (needs to be resolved base method)
     * eax = method->clazz
    */
.LOP_INVOKE_SUPER_resolve:
    SPILL_TMP(%eax)                     # method->clazz
    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
    movzwl  2(rPC),%ecx                 # ecx<- BBBB
    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
    SPILL(rPC)
    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
    UNSPILL(rPC)
    testl   %eax,%eax                   # got null?
    movl    %eax,%ecx                   # ecx<- resolved base method
    UNSPILL_TMP(%eax)                   # restore method->clazz
    jne     .LOP_INVOKE_SUPER_continue        # good to go - continue
    jmp     common_exceptionThrown      # handle exception

    /*
     * Throw a NoSuchMethodError with the method name as the message.
     *  ecx = resolved base method
     */
.LOP_INVOKE_SUPER_nsm:
    movl    offMethod_name(%ecx),%eax
    mov     %eax,OUT_ARG1(%esp)
    jmp     common_errNoSuchMethod

/* continuation for OP_INVOKE_DIRECT */

    /*
     * On entry:
     *   TMP_SPILL  <- "this" register
     * Things a bit ugly on this path, but it's the less
     * frequent one.  We'll have to do some reloading.
     */
.LOP_INVOKE_DIRECT_resolve:
     SPILL_TMP(%ecx)
     GET_GLUE(%ecx)
     UNSPILL(rPC)
     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
     movl     %eax,OUT_ARG1(%esp)
     movl     %ecx,OUT_ARG0(%esp)
     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
     UNSPILL_TMP(%ecx)
     testl    %eax,%eax
     jne      .LOP_INVOKE_DIRECT_finish
     UNSPILL(rPC)
     jmp      common_exceptionThrown

/* continuation for OP_INVOKE_STATIC */

.LOP_INVOKE_STATIC_continue:
    movl      $METHOD_STATIC,%eax
    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
    SPILL(rPC)
    call      dvmResolveMethod          # call(clazz,ref,flags)
    UNSPILL(rPC)
    testl     %eax,%eax                 # got null?
    jne       common_invokeMethodNoRange
    jmp       common_exceptionThrown

/* continuation for OP_INVOKE_INTERFACE */

.LOP_INVOKE_INTERFACE_continue:
    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
    UNSPILL(rPC)
    testl      %eax,%eax
    je         common_exceptionThrown
    jmp        common_invokeMethodNoRange

/* continuation for OP_INVOKE_VIRTUAL_RANGE */


.LOP_INVOKE_VIRTUAL_RANGE_more:
    movl      offMethod_clazz(%eax),%eax  # ecx<- method->clazz
    movl      %eax,OUT_ARG0(%esp)         # arg0<- clazz
    movl      $METHOD_VIRTUAL,OUT_ARG2(%esp) # arg2<- flags
    call      dvmResolveMethod            # eax<- call(clazz, ref, flags)
    UNSPILL(rPC)
    testl     %eax,%eax                   # got null?
    jne       .LOP_INVOKE_VIRTUAL_RANGE_continue        # no, continue
    jmp       common_exceptionThrown      # yes, handle exception

    /* At this point:
     *   eax = resolved base method
     *   ecx = scratch
     */
.LOP_INVOKE_VIRTUAL_RANGE_continue:
    movzwl    4(rPC),%ecx               # ecx<- GFED or CCCC
    .if       (!1)
    andl      $0xf,%ecx                # ecx<- D (or stays CCCC)
    .endif
    GET_VREG(%ecx,%ecx)                 # ecx<- "this"
    movzwl    offMethod_methodIndex(%eax),%eax  # eax<- baseMethod->methodIndex
    testl     %ecx,%ecx                 # null this?
    je        common_errNullObject      # go if so
    movl      offObject_clazz(%ecx),%ecx  # ecx<- thisPtr->clazz
    movl      offClassObject_vtable(%ecx),%ecx # ecx<- thisPtr->clazz->vtable
    movl      (%ecx,%eax,4),%eax        # eax<- vtable[methodIndex]
    jmp       common_invokeMethodRange

/* continuation for OP_INVOKE_SUPER_RANGE */

    /*
     * At this point:
     *  ecx = resolved base method [r0]
     *  eax = method->clazz [r9]
     */
.LOP_INVOKE_SUPER_RANGE_continue:
    movl    offClassObject_super(%eax),%eax   # eax<- method->clazz->super
    movzwl  offMethod_methodIndex(%ecx),%ecx  # ecx<- baseMthod->methodIndex
    cmpl    offClassObject_vtableCount(%eax),%ecx # compare(methodIndex,vtableCount)
    jae     .LOP_INVOKE_SUPER_RANGE_nsm           # method not present in superclass
    movl    offClassObject_vtable(%eax),%eax   # eax<- ...clazz->super->vtable
    movl    (%eax,%ecx,4),%eax        # eax<- vtable[methodIndex]
    jmp     common_invokeMethodRange


    /* At this point:
     * ecx = null (needs to be resolved base method)
     * eax = method->clazz
    */
.LOP_INVOKE_SUPER_RANGE_resolve:
    SPILL_TMP(%eax)                     # method->clazz
    movl    %eax,OUT_ARG0(%esp)         # arg0<- method->clazz
    movzwl  2(rPC),%ecx                 # ecx<- BBBB
    movl    $METHOD_VIRTUAL,OUT_ARG2(%esp)  # arg2<- resolver method type
    movl    %ecx,OUT_ARG1(%esp)         # arg1<- ref
    SPILL(rPC)
    call    dvmResolveMethod            # eax<- call(clazz, ref, flags)
    UNSPILL(rPC)
    testl   %eax,%eax                   # got null?
    movl    %eax,%ecx                   # ecx<- resolved base method
    UNSPILL_TMP(%eax)                   # restore method->clazz
    jne     .LOP_INVOKE_SUPER_RANGE_continue        # good to go - continue
    jmp     common_exceptionThrown      # handle exception

    /*
     * Throw a NoSuchMethodError with the method name as the message.
     *  ecx = resolved base method
     */
.LOP_INVOKE_SUPER_RANGE_nsm:
    movl    offMethod_name(%ecx),%eax
    mov     %eax,OUT_ARG1(%esp)
    jmp     common_errNoSuchMethod

/* continuation for OP_INVOKE_DIRECT_RANGE */

    /*
     * On entry:
     *   TMP_SPILL  <- "this" register
     * Things a bit ugly on this path, but it's the less
     * frequent one.  We'll have to do some reloading.
     */
.LOP_INVOKE_DIRECT_RANGE_resolve:
     SPILL_TMP(%ecx)
     GET_GLUE(%ecx)
     UNSPILL(rPC)
     movl     offGlue_method(%ecx),%ecx  # ecx<- glue->method
     movzwl   2(rPC),%eax      # reference (BBBB or CCCC)
     movl     offMethod_clazz(%ecx),%ecx # ecx<- method->clazz
     movl     $METHOD_DIRECT,OUT_ARG2(%esp)
     movl     %eax,OUT_ARG1(%esp)
     movl     %ecx,OUT_ARG0(%esp)
     call     dvmResolveMethod # eax<- call(clazz, ref, flags)
     UNSPILL_TMP(%ecx)
     testl    %eax,%eax
     jne      .LOP_INVOKE_DIRECT_RANGE_finish
     UNSPILL(rPC)
     jmp      common_exceptionThrown

/* continuation for OP_INVOKE_STATIC_RANGE */

.LOP_INVOKE_STATIC_RANGE_continue:
    movl      $METHOD_STATIC,%eax
    movl      %eax,OUT_ARG2(%esp)       # arg2<- flags
    SPILL(rPC)
    call      dvmResolveMethod          # call(clazz,ref,flags)
    UNSPILL(rPC)
    testl     %eax,%eax                 # got null?
    jne       common_invokeMethodRange
    jmp       common_exceptionThrown

/* continuation for OP_INVOKE_INTERFACE_RANGE */

.LOP_INVOKE_INTERFACE_RANGE_continue:
    call       dvmFindInterfaceMethodInCache # eax<- call(class, ref, method, dex)
    UNSPILL(rPC)
    testl      %eax,%eax
    je         common_exceptionThrown
    jmp        common_invokeMethodRange

/* continuation for OP_FLOAT_TO_INT */


.LOP_FLOAT_TO_INT_continue:
    .if 0
    movl     $0x80000000,%eax
    xorl     4(rFP,%ecx,4),%eax
    orl      (rFP,%ecx,4),%eax
    .else
    cmpl     $0x80000000,(rFP,%ecx,4)
    .endif
    je       .LOP_FLOAT_TO_INT_special_case # fix up result

.LOP_FLOAT_TO_INT_finish:
    ADVANCE_PC(1)
    GOTO_NEXT

.LOP_FLOAT_TO_INT_special_case:
    fnstsw   %ax
    sahf
    jp       .LOP_FLOAT_TO_INT_isNaN
    adcl     $-1,(rFP,%ecx,4)
    .if 0
    adcl     $-1,4(rFP,%ecx,4)
    .endif
   jmp       .LOP_FLOAT_TO_INT_finish
.LOP_FLOAT_TO_INT_isNaN:
    movl      $0,(rFP,%ecx,4)
    .if 0
    movl      $0,4(rFP,%ecx,4)
    .endif
    jmp       .LOP_FLOAT_TO_INT_finish

/* continuation for OP_FLOAT_TO_LONG */


.LOP_FLOAT_TO_LONG_continue:
    .if 1
    movl     $0x80000000,%eax
    xorl     4(rFP,%ecx,4),%eax
    orl      (rFP,%ecx,4),%eax
    .else
    cmpl     $0x80000000,(rFP,%ecx,4)
    .endif
    je       .LOP_FLOAT_TO_LONG_special_case # fix up result

.LOP_FLOAT_TO_LONG_finish:
    ADVANCE_PC(1)
    GOTO_NEXT

.LOP_FLOAT_TO_LONG_special_case:
    fnstsw   %ax
    sahf
    jp       .LOP_FLOAT_TO_LONG_isNaN
    adcl     $-1,(rFP,%ecx,4)
    .if 1
    adcl     $-1,4(rFP,%ecx,4)
    .endif
   jmp       .LOP_FLOAT_TO_LONG_finish
.LOP_FLOAT_TO_LONG_isNaN:
    movl      $0,(rFP,%ecx,4)
    .if 1
    movl      $0,4(rFP,%ecx,4)
    .endif
    jmp       .LOP_FLOAT_TO_LONG_finish

/* continuation for OP_DOUBLE_TO_INT */


.LOP_DOUBLE_TO_INT_continue:
    .if 0
    movl     $0x80000000,%eax
    xorl     4(rFP,%ecx,4),%eax
    orl      (rFP,%ecx,4),%eax
    .else
    cmpl     $0x80000000,(rFP,%ecx,4)
    .endif
    je       .LOP_DOUBLE_TO_INT_special_case # fix up result

.LOP_DOUBLE_TO_INT_finish:
    ADVANCE_PC(1)
    GOTO_NEXT

.LOP_DOUBLE_TO_INT_special_case:
    fnstsw   %ax
    sahf
    jp       .LOP_DOUBLE_TO_INT_isNaN
    adcl     $-1,(rFP,%ecx,4)
    .if 0
    adcl     $-1,4(rFP,%ecx,4)
    .endif
   jmp       .LOP_DOUBLE_TO_INT_finish
.LOP_DOUBLE_TO_INT_isNaN:
    movl      $0,(rFP,%ecx,4)
    .if 0
    movl      $0,4(rFP,%ecx,4)
    .endif
    jmp       .LOP_DOUBLE_TO_INT_finish

/* continuation for OP_DOUBLE_TO_LONG */


.LOP_DOUBLE_TO_LONG_continue:
    .if 1
    movl     $0x80000000,%eax
    xorl     4(rFP,%ecx,4),%eax
    orl      (rFP,%ecx,4),%eax
    .else
    cmpl     $0x80000000,(rFP,%ecx,4)
    .endif
    je       .LOP_DOUBLE_TO_LONG_special_case # fix up result

.LOP_DOUBLE_TO_LONG_finish:
    ADVANCE_PC(1)
    GOTO_NEXT

.LOP_DOUBLE_TO_LONG_special_case:
    fnstsw   %ax
    sahf
    jp       .LOP_DOUBLE_TO_LONG_isNaN
    adcl     $-1,(rFP,%ecx,4)
    .if 1
    adcl     $-1,4(rFP,%ecx,4)
    .endif
   jmp       .LOP_DOUBLE_TO_LONG_finish
.LOP_DOUBLE_TO_LONG_isNaN:
    movl      $0,(rFP,%ecx,4)
    .if 1
    movl      $0,4(rFP,%ecx,4)
    .endif
    jmp       .LOP_DOUBLE_TO_LONG_finish

/* continuation for OP_DIV_INT */
.LOP_DIV_INT_continue_div:
    cltd
    idivl   %ecx
.LOP_DIV_INT_finish_div:
    movzbl   rINST_HI,%ecx         # ecl<- AA
    SET_VREG(%eax,%ecx)
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_REM_INT */
.LOP_REM_INT_continue_div:
    cltd
    idivl   %ecx
.LOP_REM_INT_finish_div:
    movzbl   rINST_HI,%ecx         # ecl<- AA
    SET_VREG(%edx,%ecx)
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_MUL_LONG */

.LOP_MUL_LONG_continue:
    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
    movzbl    rINST_HI,%ecx       # ecx<- A
    movl      %edx,4(rFP,%ecx,4)  # v[B+1]<- %edx
    UNSPILL(rPC)                  # restore rPC/%edx
    FETCH_INST_WORD(2)
    UNSPILL(rIBASE)
    movl      %eax,(rFP,%ecx,4)   # v[B]<- %eax
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_DIV_LONG */

.LOP_DIV_LONG_continue:
    call     __divdi3
.LOP_DIV_LONG_finish:
    movzbl   rINST_HI,%ecx
    SET_VREG_WORD(rPC,%ecx,1)
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

.LOP_DIV_LONG_check_zero:
    testl   rPC,rPC
    jne     .LOP_DIV_LONG_notSpecial
    UNSPILL(rPC)
    jmp     common_errDivideByZero
.LOP_DIV_LONG_check_neg1:
    testl   rPC,%eax
    jne     .LOP_DIV_LONG_notSpecial
    GET_VREG_WORD(rPC,%ecx,0)
    GET_VREG_WORD(%ecx,%ecx,1)
    testl    rPC,rPC
    jne      .LOP_DIV_LONG_notSpecial1
    cmpl     $0x80000000,%ecx
    jne      .LOP_DIV_LONG_notSpecial1
    /* minint / -1, return minint on div, 0 on rem */
    xorl     %eax,%eax
    movl     $0x80000000,%edx
    jmp      .LOP_DIV_LONG_finish

/* continuation for OP_REM_LONG */

.LOP_REM_LONG_continue:
    call     __moddi3
.LOP_REM_LONG_finish:
    movzbl   rINST_HI,%ecx
    SET_VREG_WORD(rPC,%ecx,1)
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

.LOP_REM_LONG_check_zero:
    testl   rPC,rPC
    jne     .LOP_REM_LONG_notSpecial
    UNSPILL(rPC)
    jmp     common_errDivideByZero
.LOP_REM_LONG_check_neg1:
    testl   rPC,%eax
    jne     .LOP_REM_LONG_notSpecial
    GET_VREG_WORD(rPC,%ecx,0)
    GET_VREG_WORD(%ecx,%ecx,1)
    testl    rPC,rPC
    jne      .LOP_REM_LONG_notSpecial1
    cmpl     $0x80000000,%ecx
    jne      .LOP_REM_LONG_notSpecial1
    /* minint / -1, return minint on div, 0 on rem */
    xorl     %eax,%eax
    movl     $0,%edx
    jmp      .LOP_REM_LONG_finish

/* continuation for OP_SHL_LONG */

.LOP_SHL_LONG_finish:
    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- %eax
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_SHR_LONG */


.LOP_SHR_LONG_finish:
    SET_VREG_WORD(%eax,%ecx,0)         # v[AA+0]<- eax
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_USHR_LONG */


.LOP_USHR_LONG_finish:
    SET_VREG_WORD(%eax,%ecx,0)        # v[BB+0]<- eax
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_DIV_INT_2ADDR */
.LOP_DIV_INT_2ADDR_continue_div2addr:
    cltd
    idivl   %ecx
.LOP_DIV_INT_2ADDR_finish_div2addr:
    SET_VREG(%eax,rINST_FULL)
    UNSPILL(rPC)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_REM_INT_2ADDR */
.LOP_REM_INT_2ADDR_continue_div2addr:
    cltd
    idivl   %ecx
.LOP_REM_INT_2ADDR_finish_div2addr:
    SET_VREG(%edx,rINST_FULL)
    UNSPILL(rPC)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_MUL_LONG_2ADDR */

.LOP_MUL_LONG_2ADDR_continue:
    leal      (%ecx,%edx),%edx    # full result now in %edx:%eax
    movl      %edx,4(rIBASE)      # v[A+1]<- %edx
    UNSPILL(rPC)                  # restore rPC/%edx
    FETCH_INST_WORD(1)
    movl      %eax,(rIBASE)       # v[A]<- %eax
    UNSPILL(rFP)
    UNSPILL(rIBASE)
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_DIV_LONG_2ADDR */

.LOP_DIV_LONG_2ADDR_continue:
    movl     %eax,OUT_ARG3(%esp)
    movl     rPC,OUT_ARG0(%esp)
    movl     %ecx,OUT_ARG1(%esp)
    call     __divdi3
.LOP_DIV_LONG_2ADDR_finish:
    movl     rINST_FULL,%ecx
    SET_VREG_WORD(rPC,%ecx,1)
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

.LOP_DIV_LONG_2ADDR_check_zero:
    testl   rPC,rPC
    jne     .LOP_DIV_LONG_2ADDR_notSpecial
    UNSPILL(rPC)
    jmp     common_errDivideByZero
.LOP_DIV_LONG_2ADDR_check_neg1:
    testl   rPC,%eax
    jne     .LOP_DIV_LONG_2ADDR_notSpecial
    GET_VREG_WORD(rPC,rINST_FULL,0)
    GET_VREG_WORD(%ecx,rINST_FULL,1)
    testl    rPC,rPC
    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
    cmpl     $0x80000000,%ecx
    jne      .LOP_DIV_LONG_2ADDR_notSpecial1
    /* minint / -1, return minint on div, 0 on rem */
    xorl     %eax,%eax
    movl     $0x80000000,%edx
    jmp      .LOP_DIV_LONG_2ADDR_finish

/* continuation for OP_REM_LONG_2ADDR */

.LOP_REM_LONG_2ADDR_continue:
    movl     %eax,OUT_ARG3(%esp)
    movl     rPC,OUT_ARG0(%esp)
    movl     %ecx,OUT_ARG1(%esp)
    call     __moddi3
.LOP_REM_LONG_2ADDR_finish:
    movl     rINST_FULL,%ecx
    SET_VREG_WORD(rPC,%ecx,1)
    UNSPILL(rPC)
    SET_VREG_WORD(%eax,%ecx,0)
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

.LOP_REM_LONG_2ADDR_check_zero:
    testl   rPC,rPC
    jne     .LOP_REM_LONG_2ADDR_notSpecial
    UNSPILL(rPC)
    jmp     common_errDivideByZero
.LOP_REM_LONG_2ADDR_check_neg1:
    testl   rPC,%eax
    jne     .LOP_REM_LONG_2ADDR_notSpecial
    GET_VREG_WORD(rPC,rINST_FULL,0)
    GET_VREG_WORD(%ecx,rINST_FULL,1)
    testl    rPC,rPC
    jne      .LOP_REM_LONG_2ADDR_notSpecial1
    cmpl     $0x80000000,%ecx
    jne      .LOP_REM_LONG_2ADDR_notSpecial1
    /* minint / -1, return minint on div, 0 on rem */
    xorl     %eax,%eax
    movl     $0,%edx
    jmp      .LOP_REM_LONG_2ADDR_finish

/* continuation for OP_SHL_LONG_2ADDR */


.LOP_SHL_LONG_2ADDR_finish:
    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_SHR_LONG_2ADDR */


.LOP_SHR_LONG_2ADDR_finish:
    SET_VREG_WORD(%eax,rINST_FULL,0)  # v[AA+0]<- eax
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_USHR_LONG_2ADDR */


.LOP_USHR_LONG_2ADDR_finish:
    SET_VREG_WORD(%eax,rINST_FULL,0)   # v[AA+0]<- eax
    FETCH_INST_WORD(1)
    ADVANCE_PC(1)
    GOTO_NEXT

/* continuation for OP_DIV_INT_LIT16 */
.LOP_DIV_INT_LIT16_continue_div:
    cltd
    idivl   %ecx
.LOP_DIV_INT_LIT16_finish_div:
    SET_VREG(%eax,rINST_FULL)
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_REM_INT_LIT16 */
.LOP_REM_INT_LIT16_continue_div:
    cltd
    idivl   %ecx
.LOP_REM_INT_LIT16_finish_div:
    SET_VREG(%edx,rINST_FULL)
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_DIV_INT_LIT8 */
.LOP_DIV_INT_LIT8_continue_div:
    cltd
    idivl   %ecx
.LOP_DIV_INT_LIT8_finish_div:
    SET_VREG(%eax,rINST_FULL)
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_REM_INT_LIT8 */
.LOP_REM_INT_LIT8_continue_div:
    cltd
    idivl   %ecx
.LOP_REM_INT_LIT8_finish_div:
    SET_VREG(%edx,rINST_FULL)
    UNSPILL(rPC)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IGET_VOLATILE */


.LOP_IGET_VOLATILE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_VOLATILE_finish
    jmp     common_exceptionThrown

.LOP_IGET_VOLATILE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_VOLATILE */


.LOP_IPUT_VOLATILE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_VOLATILE_finish
    jmp     common_exceptionThrown

.LOP_IPUT_VOLATILE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl   rINST_FULL,(%ecx,%eax,1)            # obj.field <- v[A](8/16/32 bits)
    FETCH_INST_WORD(2)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_SGET_VOLATILE */

    /*
     * Go resolve the field
     */
.LOP_SGET_VOLATILE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_VOLATILE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_VOLATILE */

    /*
     * Go resolve the field
     */
.LOP_SPUT_VOLATILE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_VOLATILE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_IGET_OBJECT_VOLATILE */


.LOP_IGET_OBJECT_VOLATILE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IGET_OBJECT_VOLATILE_finish
    jmp     common_exceptionThrown

.LOP_IGET_OBJECT_VOLATILE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl   (%ecx,%eax,1),%ecx                   # ecx<- obj.field (8/16/32 bits)
    movl    rINST_FULL,%eax                      # eax<- A
    FETCH_INST_WORD(2)
    SET_VREG(%ecx,%eax)
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_EXECUTE_INLINE */

.LOP_EXECUTE_INLINE_continue:
    /*
     * Extract args, call function.
     *  ecx = #of args (0-4)
     *  eax = call index
     *  @esp = return addr
     *  esp is -4 from normal
     *
     *  Go ahead and load all 4 args, even if not used.
     */
    movzwl    4(rPC),rPC

    movl      $0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $4,rPC
    movl      %ecx,4+OUT_ARG0(%esp)

    movl      $0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $4,rPC
    movl      %ecx,4+OUT_ARG1(%esp)

    movl      $0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $4,rPC
    movl      %ecx,4+OUT_ARG2(%esp)

    movl      $0xf,%ecx
    andl      rPC,%ecx
    GET_VREG(%ecx,%ecx)
    sarl      $4,rPC
    movl      %ecx,4+OUT_ARG3(%esp)

    sall      $4,%eax      # index *= sizeof(table entry)
    jmp       *gDvmInlineOpsTable(%eax)
    # will return to caller of .LOP_EXECUTE_INLINE_continue

/* continuation for OP_IPUT_OBJECT_QUICK */

.LOP_IPUT_OBJECT_QUICK_finish:
    testl     rINST_FULL,rINST_FULL         # did we store null?
    FETCH_INST_WORD(2)
    movl      offGlue_cardTable(%eax),%eax  # get card table base
    je        1f                            # skip card mark if null store
    shrl      $GC_CARD_SHIFT,%ecx          # object head to card number
    movb      %al,(%eax,%ecx)               # mark card based on object head
1:
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_IPUT_OBJECT_VOLATILE */


.LOP_IPUT_OBJECT_VOLATILE_resolve:
    EXPORT_PC()
    SPILL(rPC)
    movl    offGlue_method(rIBASE),rPC            # rPC<- current method
    UNSPILL(rIBASE)
    movl    offMethod_clazz(rPC),rPC              # rPC<- method->clazz
    SPILL_TMP(%ecx)                               # save object pointer across call
    movl    rPC,OUT_ARG0(%esp)                    # pass in method->clazz
    call    dvmResolveInstField                   #  ... to dvmResolveInstField
    UNSPILL_TMP(%ecx)
    UNSPILL(rPC)
    testl   %eax,%eax                             #  ... which returns InstrField ptr
    jne     .LOP_IPUT_OBJECT_VOLATILE_finish
    jmp     common_exceptionThrown

.LOP_IPUT_OBJECT_VOLATILE_finish:
    /*
     * Currently:
     *   eax holds resolved field
     *   ecx holds object
     *   rIBASE is scratch, but needs to be unspilled
     *   rINST_FULL holds A
     */
    GET_VREG(rINST_FULL,rINST_FULL)              # rINST_FULL<- v[A]
    movl    offInstField_byteOffset(%eax),%eax   # eax<- byte offset of field
    UNSPILL(rIBASE)
    testl   %ecx,%ecx                            # object null?
    je      common_errNullObject                 # object was null
    movl    rINST_FULL,(%ecx,%eax)          # obj.field <- v[A](8/16/32 bits)
    GET_GLUE(%eax)
    testl   rINST_FULL,rINST_FULL                # stored a NULL?
    movl    offGlue_cardTable(%eax),%eax         # get card table base
    FETCH_INST_WORD(2)
    je      1f                                   # skip card mark if null store
    shrl    $GC_CARD_SHIFT,%ecx                 # object head to card number
    movb    %al,(%eax,%ecx)                      # mark card using object head
1:
    ADVANCE_PC(2)
    GOTO_NEXT

/* continuation for OP_SGET_OBJECT_VOLATILE */

    /*
     * Go resolve the field
     */
.LOP_SGET_OBJECT_VOLATILE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SGET_OBJECT_VOLATILE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

/* continuation for OP_SPUT_OBJECT_VOLATILE */


.LOP_SPUT_OBJECT_VOLATILE_continue:
    movl      %ecx,offStaticField_value(%eax)    # do the store
    testl     %ecx,%ecx                          # stored null object ptr?
    FETCH_INST_WORD(2)
    je        1f                                 # skip card mark if null
    GET_GLUE(%ecx)
    movl      offField_clazz(%eax),%eax          # eax<- field->clazz
    movl      offGlue_cardTable(%ecx),%ecx       # get card table base
    shrl      $GC_CARD_SHIFT,%eax               # head to card number
    movb      %cl,(%ecx,%eax)                    # mark card
1:
    ADVANCE_PC(2)
    GOTO_NEXT

.LOP_SPUT_OBJECT_VOLATILE_resolve:
    GET_GLUE(%ecx)
    movzwl   2(rPC),%eax                        # eax<- field ref BBBB
    movl     offGlue_method(%ecx),%ecx          # ecx<- current method
    EXPORT_PC()                                 # could throw, need to export
    movl     offMethod_clazz(%ecx),%ecx         # ecx<- method->clazz
    SPILL(rPC)
    movl     %eax,OUT_ARG1(%esp)
    movl     %ecx,OUT_ARG0(%esp)
    call     dvmResolveStaticField              # eax<- resolved StaticField ptr
    UNSPILL(rPC)
    testl    %eax,%eax
    jne      .LOP_SPUT_OBJECT_VOLATILE_finish                 # success, continue
    jmp      common_exceptionThrown             # no, handle exception

    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
    .global dvmAsmSisterEnd
dvmAsmSisterEnd:

/* File: x86/entry.S */
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


    .text
    .global dvmMterpStdRun
    .type   dvmMterpStdRun, %function
/*
 * bool dvmMterpStdRun(MterpGlue* glue)
 *
 * Interpreter entry point.  Returns changeInterp.
 *
 */
dvmMterpStdRun:
    push    %ebp
    movl    %esp,%ebp
    push    %edi
    push    %esi
    push    %ebx

/* at this point, stack is misaligned by 1 word
   We're allocating spill space for 6 words, plus
   outgoing argument (5 words) and local variables
   (4 words) - 15 words or 60 bytes total. See
   diagram in header.S
*/
    subl   $60,%esp

/* Set up "named" registers */
    movl    IN_ARG0(%ebp),%ecx
    movl    %ecx,rGLUE_SPILL(%ebp)
    LOAD_PC_FROM_GLUE(%ecx)
    LOAD_FP_FROM_GLUE(%ecx)
    movl    $dvmAsmInstructionStart,rIBASE

/* Remember %esp for future "longjmp" */
    movl    %esp,offGlue_bailPtr(%ecx)

/* How to start? */
    movb    offGlue_entryPoint(%ecx),%al

/* Normal start? */
    cmpb    $kInterpEntryInstr,%al
    jne     .Lnot_instr

   /* Normal case: start executing the instruction at rPC */
    FETCH_INST()
    GOTO_NEXT

.Lnot_instr:
    /* Reset to normal case */
    movb   $kInterpEntryInstr,offGlue_entryPoint(%ecx)
    cmpb   $kInterpEntryReturn,%al
    je     common_returnFromMethod
    cmpb   $kInterpEntryThrow,%al
    je     common_exceptionThrown
    movzx  %al,%eax
    movl   %eax,OUT_ARG1(%esp)
    movl   $.LstrBadEntryPoint,OUT_ARG0(%esp)
    call   printf
    call   dvmAbort
    /* Not reached */


    .global dvmMterpStdBail
    .type   dvmMterpStdBail, %function
/*
 * void dvmMterpStdBail(MterpGlue* glue, bool changeInterp)
 *
 * Restore the stack pointer and PC from the save point established on entry.
 * This is essentially the same as a longjmp, but should be cheaper.  The
 * last instruction causes us to return to whoever called dvmMterpStdRun.
 *
 * We're not going to build a standard frame here, so the arg accesses will
 * look a little strange.
 *
 * On entry:
 *  esp+4 (arg0)  MterpGlue* glue
 *  esp+8 (arg1)  bool changeInterp
 */
dvmMterpStdBail:
    movl    4(%esp),%ecx                 # grab glue
    movl    8(%esp),%eax                 # changeInterp to return reg
    movl    offGlue_bailPtr(%ecx),%esp   # Stack back to normal
    addl    $60,%esp                    # Strip dvmMterpStdRun's frame
    pop     %ebx
    pop     %esi
    pop     %edi
    pop     %ebp
    ret                                  # return to dvmMterpStdRun's caller


/*
 * Strings
 */
    .section    .rodata
.LstrBadEntryPoint:
    .asciz  "Bad entry point %d\n"

/* File: x86/footer.S */
/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * Common subroutines and data.
 */

/*
 * Common code when a backwards branch is taken
 *
 * On entry:
 *   ebx (a.k.a. rINST_FULL) -> PC adjustment in 16-bit words
 */
common_backwardBranch:
    GET_GLUE(%ecx)
    call   common_periodicChecks  # Note: expects rPC to be preserved
    ADVANCE_PC_INDEXED(rINST_FULL)
    FETCH_INST()
    GOTO_NEXT



/*
 * Common code for method invocation with range.
 *
 * On entry:
 *   eax = Method* methodToCall
 *   rINST trashed, must reload
 */

common_invokeMethodRange:
.LinvokeNewRange:

   /*
    * prepare to copy args to "outs" area of current frame
    */

    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- AA
    movzwl      4(rPC), %ecx            # %ecx<- CCCC
    SPILL(rPC)
    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea
    test        rINST_FULL, rINST_FULL
    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- AA
    jz          .LinvokeArgsDone        # no args; jump to args done


   /*
    * %eax=methodToCall, %ecx=CCCC, LOCAL0_OFFSET(%ebp)=count, %edx=&outs (&stackSaveArea)
    * (very few methods have > 10 args; could unroll for common cases)
    */

    movl        %ebx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- save %ebx
    lea         (rFP, %ecx, 4), %ecx    # %ecx<- &vCCCC
    shll        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
    subl        LOCAL0_OFFSET(%ebp), %edx       # %edx<- update &outs
    shrl        $2, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- offset
1:
    movl        (%ecx), %ebx            # %ebx<- vCCCC
    lea         4(%ecx), %ecx           # %ecx<- &vCCCC++
    subl        $1, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET<- LOCAL0_OFFSET--
    movl        %ebx, (%edx)            # *outs<- vCCCC
    lea         4(%edx), %edx           # outs++
    jne         1b                      # loop if count (LOCAL0_OFFSET(%ebp)) not zero
    movl        LOCAL1_OFFSET(%ebp), %ebx       # %ebx<- restore %ebx
    jmp         .LinvokeArgsDone        # continue

   /*
    * %eax is "Method* methodToCall", the method we're trying to call
    * prepare to copy args to "outs" area of current frame
    */

common_invokeMethodNoRange:
.LinvokeNewNoRange:
    movzbl      1(rPC),rINST_FULL       # rINST_FULL<- BA
    SPILL(rPC)
    movl        rINST_FULL, LOCAL0_OFFSET(%ebp) # LOCAL0_OFFSET(%ebp)<- BA
    shrl        $4, LOCAL0_OFFSET(%ebp)        # LOCAL0_OFFSET(%ebp)<- B
    je          .LinvokeArgsDone        # no args; jump to args done
    movzwl      4(rPC), %ecx            # %ecx<- GFED
    SAVEAREA_FROM_FP(%edx,rFP)          # %edx<- &StackSaveArea

   /*
    * %eax=methodToCall, %ecx=GFED, LOCAL0_OFFSET(%ebp)=count, %edx=outs
    */

.LinvokeNonRange:
    cmp         $2, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 2
    movl        %ecx, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- GFED
    jl          1f                      # handle 1 arg
    je          2f                      # handle 2 args
    cmp         $4, LOCAL0_OFFSET(%ebp)        # compare LOCAL0_OFFSET(%ebp) to 4
    jl          3f                      # handle 3 args
    je          4f                      # handle 4 args
5:
    andl        $15, rINST_FULL        # rINST<- A
    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
    movl        (rFP, rINST_FULL, 4), %ecx # %ecx<- vA
    movl        %ecx, (%edx)            # *outs<- vA
    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
4:
    shr         $12, %ecx              # %ecx<- G
    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vG
    movl        %ecx, (%edx)            # *outs<- vG
    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
3:
    and         $0x0f00, %ecx          # %ecx<- 0F00
    shr         $8, %ecx               # %ecx<- F
    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vF
    movl        %ecx, (%edx)            # *outs<- vF
    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
2:
    and         $0x00f0, %ecx          # %ecx<- 00E0
    shr         $4, %ecx               # %ecx<- E
    lea         -4(%edx), %edx          # %edx<- update &outs; &outs--
    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vE
    movl        %ecx, (%edx)            # *outs<- vE
    movl        LOCAL1_OFFSET(%ebp), %ecx       # %ecx<- GFED
1:
    and         $0x000f, %ecx          # %ecx<- 000D
    movl        (rFP, %ecx, 4), %ecx    # %ecx<- vD
    movl        %ecx, -4(%edx)          # *--outs<- vD
0:

   /*
    * %eax is "Method* methodToCall", the method we're trying to call
    * find space for the new stack frame, check for overflow
    */

.LinvokeArgsDone:
    movzwl      offMethod_registersSize(%eax), %edx # %edx<- methodToCall->regsSize
    movzwl      offMethod_outsSize(%eax), %ecx # %ecx<- methodToCall->outsSize
    movl        %eax, LOCAL0_OFFSET(%ebp)       # LOCAL0_OFFSET<- methodToCall
    shl         $2, %edx               # %edx<- update offset
    SAVEAREA_FROM_FP(%eax,rFP)          # %eax<- &StackSaveArea
    subl        %edx, %eax              # %eax<- newFP; (old savearea - regsSize)
    GET_GLUE(%edx)                      # %edx<- pMterpGlue
    movl        %eax, LOCAL1_OFFSET(%ebp)       # LOCAL1_OFFSET(%ebp)<- &outs
    subl        $sizeofStackSaveArea, %eax # %eax<- newSaveArea (stack save area using newFP)
    movl        offGlue_interpStackEnd(%edx), %edx # %edx<- glue->interpStackEnd
    movl        %edx, LOCAL2_OFFSET(%ebp)       # LOCAL2_OFFSET<- glue->interpStackEnd
    shl         $2, %ecx               # %ecx<- update offset for outsSize
    movl        %eax, %edx              # %edx<- newSaveArea
    sub         %ecx, %eax              # %eax<- bottom; (newSaveArea - outsSize)
    cmp         LOCAL2_OFFSET(%ebp), %eax       # compare interpStackEnd and bottom
    movl        LOCAL0_OFFSET(%ebp), %eax       # %eax<- restore methodToCall
    jl          .LstackOverflow         # handle frame overflow

   /*
    * set up newSaveArea
    */

#ifdef EASY_GDB
    SAVEAREA_FROM_FP(%ecx,rFP)          # %ecx<- &StackSaveArea
    movl        %ecx, offStackSaveArea_prevSave(%edx) # newSaveArea->prevSave<- &outs
#endif
    movl        rFP, offStackSaveArea_prevFrame(%edx) # newSaveArea->prevFrame<- rFP
    movl        rPC_SPILL(%ebp), %ecx
    movl        %ecx, offStackSaveArea_savedPc(%edx) # newSaveArea->savedPc<- rPC
    testl       $ACC_NATIVE, offMethod_accessFlags(%eax) # check for native call
    movl        %eax, offStackSaveArea_method(%edx) # newSaveArea->method<- method to call
    jne         .LinvokeNative          # handle native call

   /*
    * Update "glue" values for the new method
    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFp
    */

    movl        offMethod_clazz(%eax), %edx # %edx<- method->clazz
    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
    movl        offClassObject_pDvmDex(%edx), %edx # %edx<- method->clazz->pDvmDex
    movl        %eax, offGlue_method(%ecx) # glue->method<- methodToCall
    movl        %edx, offGlue_methodClassDex(%ecx) # glue->methodClassDex<- method->clazz->pDvmDex
    movl        offMethod_insns(%eax), rPC # rPC<- methodToCall->insns
    movl        offGlue_self(%ecx), %eax # %eax<- glue->self
    movl        LOCAL1_OFFSET(%ebp), rFP # rFP<- newFP
    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- newFP
    FETCH_INST()
    GOTO_NEXT                           # jump to methodToCall->insns

   /*
    * Prep for the native call
    * %eax=methodToCall, LOCAL1_OFFSET(%ebp)=newFP, %edx=newSaveArea
    */

.LinvokeNative:
    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
    movl        offGlue_self(%ecx), %ecx        # %ecx<- glue->self
    movl        offThread_jniLocal_topCookie(%ecx), %eax # %eax<- self->localRef->...
    movl        %eax, offStackSaveArea_localRefCookie(%edx) # newSaveArea->localRefCookie<- top
    movl        %edx, OUT_ARG4(%esp)    # save newSaveArea
    movl        LOCAL1_OFFSET(%ebp), %edx # %edx<- newFP
    movl        %edx, offThread_curFrame(%ecx)  # glue->self->curFrame<- newFP
    movl        %ecx, OUT_ARG3(%esp)    # save glue->self
    movl        %ecx, OUT_ARG2(%esp)    # push parameter glue->self
    GET_GLUE(%ecx)                      # %ecx<- pMterpGlue
    movl        OUT_ARG1(%esp), %eax    # %eax<- methodToCall
    lea         offGlue_retval(%ecx), %ecx # %ecx<- &retval
    movl        %ecx, OUT_ARG0(%esp)    # push parameter pMterpGlue
    push        %edx                    # push parameter newFP

    call        *offMethod_nativeFunc(%eax) # call methodToCall->nativeFunc
    lea         4(%esp), %esp
    movl        OUT_ARG4(%esp), %ecx    # %ecx<- newSaveArea
    movl        OUT_ARG3(%esp), %eax    # %eax<- glue->self
    movl        offStackSaveArea_localRefCookie(%ecx), %edx # %edx<- old top
    cmp         $0, offThread_exception(%eax) # check for exception
    movl        rFP, offThread_curFrame(%eax) # glue->self->curFrame<- rFP
    movl        %edx, offThread_jniLocal_topCookie(%eax) # new top <- old top
    UNSPILL(rPC)
    jne         common_exceptionThrown  # handle exception
    FETCH_INST_WORD(3)
    ADVANCE_PC(3)
    GOTO_NEXT                           # jump to next instruction

.LstackOverflow:    # eax=methodToCall
    movl        %eax, OUT_ARG1(%esp)    # push parameter methodToCall
    GET_GLUE(%eax)                      # %eax<- pMterpGlue
    movl        offGlue_self(%eax), %eax # %eax<- glue->self
    movl        %eax, OUT_ARG0(%esp)    # push parameter self
    call        dvmHandleStackOverflow  # call: (Thread* self, Method* meth)
    UNSPILL(rPC)                        # return: void
    jmp         common_exceptionThrown  # handle exception


/*
 * Common invoke code (old-style).
 * TUNING:  Rewrite along lines of new armv5 code?
 *
 * On entry:
 *   eax = Method* methodToCall
 *   ecx = bool methodCallRange
 *   rINST trashed, must reload
 */
common_invokeOld:
    movl     %ecx,OUT_ARG1(%esp)     # arg1<- methodCallRange
    GET_GLUE(%ecx)
    movzwl  (rPC),rINST_FULL         # recover rINST
    movl     %eax,OUT_ARG2(%esp)     # arg2<- method
    movzwl   4(rPC),%eax             # eax<- GFED or CCCC
    SAVE_PC_TO_GLUE(%ecx)
    SAVE_FP_TO_GLUE(%ecx)
    movzbl   rINST_HI,rINST_FULL
    movl     rINST_FULL,OUT_ARG3(%esp)# arg3<- AA
    movl     %ecx,OUT_ARG0(%esp)     # arg0<- GLUE
    movl     %eax,OUT_ARG4(%esp)     # arg4<- GFED/CCCC
    call     dvmMterp_invokeMethod
    jmp      common_resumeAfterGlueCall


/*
 * Do we need the thread to be suspended or have debugger/profiling activity?
 *
 * On entry:
 *   ebx  -> PC adjustment in 16-bit words (must be preserved)
 *   ecx  -> GLUE pointer
 *   reentry type, e.g. kInterpEntryInstr stored in rGLUE->entryPoint
 *
 * Note: A call will normally kill %eax, rPC/%edx and %ecx.  To
 *       streamline the normal case, this routine will preserve rPC and
 *       %ecx in addition to the normal caller save regs.  The save/restore
 *       is a bit ugly, but will happen in the relatively uncommon path.
 * TODO: Basic-block style Jit will need a hook here as well.  Fold it into
 *       the suspendCount check so we can get both in 1 shot.
 */
common_periodicChecks:
    movl    offGlue_pSelfSuspendCount(%ecx),%eax    # eax <- &suspendCount
    cmpl    $0,(%eax)
    jne     1f

6:
    movl   offGlue_pDebuggerActive(%ecx),%eax      # eax <- &DebuggerActive
    movl   offGlue_pActiveProfilers(%ecx),%ecx     # ecx <- &ActiveProfilers
    testl  %eax,%eax               # debugger enabled?
    je     2f
    movzbl (%eax),%eax             # get active count
2:
    orl    (%ecx),%eax             # eax <- debuggerActive | activeProfilers
    GET_GLUE(%ecx)                 # restore rGLUE
    jne    3f                      # one or both active - switch interp

5:
    ret

    /* Check for suspend */
1:
    /*  At this point, the return pointer to the caller of
     *  common_periodicChecks is on the top of stack.  We need to preserve
     *  rPC(edx) and GLUE(ecx).  We'll spill rPC, and reload GLUE.
     *  The outgoing profile is:
     *      bool dvmCheckSuspendPending(Thread* self)
     *  Because we reached here via a call, go ahead and build a new frame.
     */
    EXPORT_PC()                         # need for precise GC
    movl    offGlue_self(%ecx),%eax      # eax<- glue->self
    SPILL(rPC)                      # save edx
    push    %ebp
    movl    %esp,%ebp
    subl    $24,%esp
    movl    %eax,OUT_ARG0(%esp)
    call    dvmCheckSuspendPending
    addl    $24,%esp
    pop     %ebp
    UNSPILL(rPC)
    GET_GLUE(%ecx)

    /*
     * Need to check to see if debugger or profiler flags got set
     * while we were suspended.
     */
    jmp    6b

    /* Switch interpreters */
    /* Note: %ebx contains the 16-bit word offset to be applied to rPC to
     * "complete" the interpretation of backwards branches.  In effect, we
     * are completing the interpretation of the branch instruction here,
     * and the new interpreter will resume interpretation at the branch
     * target. However, a switch request recognized during the handling
     * of a return from method instruction results in an immediate abort,
     * and the new interpreter will resume by re-interpreting the return
     * instruction.
     */
3:
    leal    (rPC,%ebx,2),rPC       # adjust pc to show target
    GET_GLUE(%ecx)                 # bail expect GLUE already loaded
    movl    $1,rINST_FULL         # set changeInterp to true
    jmp     common_gotoBail


/*
 * Common code for handling a return instruction
 */
common_returnFromMethod:
    GET_GLUE(%ecx)
    /* Set entry mode in case we bail */
    movb    $kInterpEntryReturn,offGlue_entryPoint(%ecx)
    xorl    rINST_FULL,rINST_FULL   # zero offset in case we switch interps
    call    common_periodicChecks   # Note: expects %ecx to be preserved

    SAVEAREA_FROM_FP(%eax,rFP)                    # eax<- saveArea (old)
    movl    offStackSaveArea_prevFrame(%eax),rFP  # rFP<- prevFrame
    movl    (offStackSaveArea_method-sizeofStackSaveArea)(rFP),rINST_FULL
    cmpl    $0,rINST_FULL                        # break?
    je      common_gotoBail    # break frame, bail out completely

    movl    offStackSaveArea_savedPc(%eax),rPC    # pc<- saveArea->savedPC
    movl    offGlue_self(%ecx),%eax               # eax<- self
    movl    rINST_FULL,offGlue_method(%ecx)  # glue->method = newSave->meethod
    movl    rFP,offThread_curFrame(%eax)     # self->curFrame = fp
    movl    offMethod_clazz(rINST_FULL),%eax # eax<- method->clazz
    FETCH_INST_WORD(3)
    movl    offClassObject_pDvmDex(%eax),%eax # eax<- method->clazz->pDvmDex
    ADVANCE_PC(3)
    movl    %eax,offGlue_methodClassDex(%ecx)
    /* not bailing - restore entry mode to default */
    movb    $kInterpEntryInstr,offGlue_entryPoint(%ecx)
    GOTO_NEXT

/*
 * Prepare to strip the current frame and "longjump" back to caller of
 * dvmMterpStdRun.
 *
 * on entry:
 *    rINST_FULL holds changeInterp
 *    ecx holds glue pointer
 *
 * expected profile: dvmMterpStdBail(MterpGlue *glue, bool changeInterp)
 */
common_gotoBail:
    SAVE_PC_TO_GLUE(%ecx)                # export state to glue
    SAVE_FP_TO_GLUE(%ecx)
    movl   %ecx,OUT_ARG0(%esp)           # glue in arg0
    movl   rINST_FULL,OUT_ARG1(%esp)     # changeInterp in arg1
    call    dvmMterpStdBail              # bail out....


/*
 * After returning from a "glued" function, pull out the updated values
 * and start executing at the next instruction.
 */
 common_resumeAfterGlueCall:
     GET_GLUE(%ecx)
     LOAD_PC_FROM_GLUE(%ecx)
     LOAD_FP_FROM_GLUE(%ecx)
     FETCH_INST()
     GOTO_NEXT

/*
 * Integer divide or mod by zero
 */
common_errDivideByZero:
    EXPORT_PC()
    movl    $.LstrArithmeticException,%eax
    movl    %eax,OUT_ARG0(%esp)
    movl    $.LstrDivideByZero,%eax
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/*
 * Attempt to allocate an array with a negative size.
 */
common_errNegativeArraySize:
    EXPORT_PC()
    movl    $.LstrNegativeArraySizeException,%eax
    movl    %eax,OUT_ARG0(%esp)
    xorl    %eax,%eax
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/*
 * Attempt to allocate an array with a negative size.
 */
common_errNoSuchMethod:

    EXPORT_PC()
    movl    $.LstrNoSuchMethodError,%eax
    movl    %eax,OUT_ARG0(%esp)
    xorl    %eax,%eax
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/*
 * Hit a null object when we weren't expecting one.  Export the PC, throw a
 * NullPointerException and goto the exception processing code.
 */
common_errNullObject:
    EXPORT_PC()
    movl    $.LstrNullPointerException,%eax
    movl    %eax,OUT_ARG0(%esp)
    xorl    %eax,%eax
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/*
 * Array index exceeds max.
 */
common_errArrayIndex:
    EXPORT_PC()
    movl    $.LstrArrayIndexException,%eax
    movl    %eax,OUT_ARG0(%esp)
    xorl    %eax,%eax
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown
/*
 * Invalid array value.
 */
common_errArrayStore:
    EXPORT_PC()
    movl    $.LstrArrayStoreException,%eax
    movl    %eax,OUT_ARG0(%esp)
    xorl    %eax,%eax
    movl    %eax,OUT_ARG1(%esp)
    SPILL(rPC)
    call    dvmThrowException
    UNSPILL(rPC)
    jmp     common_exceptionThrown

/*
 * Somebody has thrown an exception.  Handle it.
 *
 * If the exception processing code returns to us (instead of falling
 * out of the interpreter), continue with whatever the next instruction
 * now happens to be.
 *
 * This does not return.
 */
common_exceptionThrown:
    GET_GLUE(%ecx)
    SAVE_PC_TO_GLUE(%ecx)
    SAVE_FP_TO_GLUE(%ecx)
    movl    %ecx,OUT_ARG0(%esp)
    call    dvmMterp_exceptionThrown
    jmp     common_resumeAfterGlueCall

common_abort:
    movl    $0xdeadf00d,%eax
    call     *%eax


/*
 * Strings
 */

    .section     .rodata
.LstrNullPointerException:
    .asciz    "Ljava/lang/NullPointerException;"
.LstrArithmeticException:
    .asciz  "Ljava/lang/ArithmeticException;"
.LstrDivideByZero:
    .asciz  "divide by zero"
.LstrArrayIndexException:
    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
.LstrArrayStoreException:
    .asciz  "Ljava/lang/ArrayStoreException;"
.LstrNegativeArraySizeException:
    .asciz  "Ljava/lang/NegativeArraySizeException;"
.LstrInstantiationError:
    .asciz  "Ljava/lang/InstantiationError;"
.LstrClassCastException:
    .asciz  "Ljava/lang/ClassCastException;"
.LstrNoSuchMethodError:
    .asciz  "Ljava/lang/NoSuchMethodError;"
.LstrInternalError:
    .asciz  "Ljava/lang/InternalError;"
.LstrFilledNewArrayNotImpl:
    .asciz  "filled-new-array only implemented for 'int'"

