Home | History | Annotate | Download | only in out
      1 /*
      2  * This file was generated automatically by gen-mterp.py for 'armv7-a'.
      3  *
      4  * --> DO NOT EDIT <--
      5  */
      6 
      7 /* File: armv5te/header.S */
      8 /*
      9  * Copyright (C) 2008 The Android Open Source Project
     10  *
     11  * Licensed under the Apache License, Version 2.0 (the "License");
     12  * you may not use this file except in compliance with the License.
     13  * You may obtain a copy of the License at
     14  *
     15  *      http://www.apache.org/licenses/LICENSE-2.0
     16  *
     17  * Unless required by applicable law or agreed to in writing, software
     18  * distributed under the License is distributed on an "AS IS" BASIS,
     19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     20  * See the License for the specific language governing permissions and
     21  * limitations under the License.
     22  */
     23 
     24 /*
     25  * ARMv5 definitions and declarations.
     26  */
     27 
     28 /*
     29 ARM EABI general notes:
     30 
     31 r0-r3 hold first 4 args to a method; they are not preserved across method calls
     32 r4-r8 are available for general use
     33 r9 is given special treatment in some situations, but not for us
     34 r10 (sl) seems to be generally available
     35 r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
     36 r12 (ip) is scratch -- not preserved across method calls
     37 r13 (sp) should be managed carefully in case a signal arrives
     38 r14 (lr) must be preserved
     39 r15 (pc) can be tinkered with directly
     40 
     41 r0 holds returns of <= 4 bytes
     42 r0-r1 hold returns of 8 bytes, low word in r0
     43 
     44 Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
     45 is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
     46 s0-s15 (d0-d7, q0-a3) do not need to be.
     47 
     48 Stack is "full descending".  Only the arguments that don't fit in the first 4
     49 registers are placed on the stack.  "sp" points at the first stacked argument
     50 (i.e. the 5th arg).
     51 
     52 VFP: single-precision results in s0, double-precision results in d0.
     53 
     54 In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
     55 64-bit quantities (long long, double) must be 64-bit aligned.
     56 */
     57 
     58 /*
     59 Mterp and ARM notes:
     60 
     61 The following registers have fixed assignments:
     62 
     63   reg nick      purpose
     64   r4  rPC       interpreted program counter, used for fetching instructions
     65   r5  rFP       interpreted frame pointer, used for accessing locals and args
     66   r6  rGLUE     MterpGlue pointer
     67   r7  rINST     first 16-bit code unit of current instruction
     68   r8  rIBASE    interpreted instruction base pointer, used for computed goto
     69 
     70 Macros are provided for common operations.  Each macro MUST emit only
     71 one instruction to make instruction-counting easier.  They MUST NOT alter
     72 unspecified registers or condition codes.
     73 */
     74 
     75 /* single-purpose registers, given names for clarity */
     76 #define rPC     r4
     77 #define rFP     r5
     78 #define rGLUE   r6
     79 #define rINST   r7
     80 #define rIBASE  r8
     81 
     82 /* save/restore the PC and/or FP from the glue struct */
     83 #define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
     84 #define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
     85 #define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
     86 #define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
     87 #define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
     88 #define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
     89 
     90 /*
     91  * "export" the PC to the stack frame, f/b/o future exception objects.  Must
     92  * be done *before* something calls dvmThrowException.
     93  *
     94  * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
     95  * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
     96  *
     97  * It's okay to do this more than once.
     98  */
     99 #define EXPORT_PC() \
    100     str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
    101 
    102 /*
    103  * Given a frame pointer, find the stack save area.
    104  *
    105  * In C this is "((StackSaveArea*)(_fp) -1)".
    106  */
    107 #define SAVEAREA_FROM_FP(_reg, _fpreg) \
    108     sub     _reg, _fpreg, #sizeofStackSaveArea
    109 
    110 /*
    111  * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
    112  */
    113 #define FETCH_INST()            ldrh    rINST, [rPC]
    114 
    115 /*
    116  * Fetch the next instruction from the specified offset.  Advances rPC
    117  * to point to the next instruction.  "_count" is in 16-bit code units.
    118  *
    119  * Because of the limited size of immediate constants on ARM, this is only
    120  * suitable for small forward movements (i.e. don't try to implement "goto"
    121  * with this).
    122  *
    123  * This must come AFTER anything that can throw an exception, or the
    124  * exception catch may miss.  (This also implies that it must come after
    125  * EXPORT_PC().)
    126  */
    127 #define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
    128 
    129 /*
    130  * The operation performed here is similar to FETCH_ADVANCE_INST, except the
    131  * src and dest registers are parameterized (not hard-wired to rPC and rINST).
    132  */
    133 #define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
    134         ldrh    _dreg, [_sreg, #(_count*2)]!
    135 
    136 /*
    137  * Fetch the next instruction from an offset specified by _reg.  Updates
    138  * rPC to point to the next instruction.  "_reg" must specify the distance
    139  * in bytes, *not* 16-bit code units, and may be a signed value.
    140  *
    141  * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
    142  * bits that hold the shift distance are used for the half/byte/sign flags.
    143  * In some cases we can pre-double _reg for free, so we require a byte offset
    144  * here.
    145  */
    146 #define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
    147 
    148 /*
    149  * Fetch a half-word code unit from an offset past the current PC.  The
    150  * "_count" value is in 16-bit code units.  Does not advance rPC.
    151  *
    152  * The "_S" variant works the same but treats the value as signed.
    153  */
    154 #define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
    155 #define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
    156 
    157 /*
    158  * Fetch one byte from an offset past the current PC.  Pass in the same
    159  * "_count" as you would for FETCH, and an additional 0/1 indicating which
    160  * byte of the halfword you want (lo/hi).
    161  */
    162 #define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
    163 
    164 /*
    165  * Put the instruction's opcode field into the specified register.
    166  */
    167 #define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
    168 
    169 /*
    170  * Put the prefetched instruction's opcode field into the specified register.
    171  */
    172 #define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
    173 
    174 /*
    175  * Begin executing the opcode in _reg.  Because this only jumps within the
    176  * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
    177  */
    178 #define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
    179 #define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
    180 #define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
    181 
    182 /*
    183  * Get/set the 32-bit value from a Dalvik register.
    184  */
    185 #define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
    186 #define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
    187 
    188 #if defined(WITH_JIT)
    189 #define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
    190 #define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
    191 #endif
    192 
    193 /*
    194  * Convert a virtual register index into an address.
    195  */
    196 #define VREG_INDEX_TO_ADDR(_reg, _vreg) \
    197         add     _reg, rFP, _vreg, lsl #2
    198 
    199 /*
    200  * This is a #include, not a %include, because we want the C pre-processor
    201  * to expand the macros into assembler assignment statements.
    202  */
    203 #include "../common/asm-constants.h"
    204 
    205 #if defined(WITH_JIT)
    206 #include "../common/jit-config.h"
    207 #endif
    208 
    209 /* File: armv7-a/platform.S */
    210 /*
    211  * ===========================================================================
    212  *  CPU-version-specific defines
    213  * ===========================================================================
    214  */
    215 
    216 /*
    217  * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
    218  * one-way branch.
    219  *
    220  * May modify IP.  Does not modify LR.
    221  */
    222 .macro  LDR_PC source
    223     ldr     pc, \source
    224 .endm
    225 
    226 /*
    227  * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
    228  * Jump to subroutine.
    229  *
    230  * May modify IP and LR.
    231  */
    232 .macro  LDR_PC_LR source
    233     mov     lr, pc
    234     ldr     pc, \source
    235 .endm
    236 
    237 /*
    238  * Macro for "LDMFD SP!, {...regs...,PC}".
    239  *
    240  * May modify IP and LR.
    241  */
    242 .macro  LDMFD_PC regs
    243     ldmfd   sp!, {\regs,pc}
    244 .endm
    245 
    246 #if !defined(ANDROID_SMP)
    247 # error "Must define ANDROID_SMP"
    248 #endif
    249 
    250 /*
    251  * Macro for data memory barrier; not meaningful pre-ARMv6K.
    252  * If the argument is nonzero, emit barrier; otherwise, emit nothing.
    253  */
    254 .macro  SMP_DMB
    255 #if ANDROID_SMP != 0
    256     dmb
    257 #else
    258     /* not SMP */
    259 #endif
    260 .endm
    261 
    262 /* File: armv5te/entry.S */
    263 /*
    264  * Copyright (C) 2008 The Android Open Source Project
    265  *
    266  * Licensed under the Apache License, Version 2.0 (the "License");
    267  * you may not use this file except in compliance with the License.
    268  * You may obtain a copy of the License at
    269  *
    270  *      http://www.apache.org/licenses/LICENSE-2.0
    271  *
    272  * Unless required by applicable law or agreed to in writing, software
    273  * distributed under the License is distributed on an "AS IS" BASIS,
    274  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    275  * See the License for the specific language governing permissions and
    276  * limitations under the License.
    277  */
    278 /*
    279  * Interpreter entry point.
    280  */
    281 
    282 /*
    283  * We don't have formal stack frames, so gdb scans upward in the code
    284  * to find the start of the function (a label with the %function type),
    285  * and then looks at the next few instructions to figure out what
    286  * got pushed onto the stack.  From this it figures out how to restore
    287  * the registers, including PC, for the previous stack frame.  If gdb
    288  * sees a non-function label, it stops scanning, so either we need to
    289  * have nothing but assembler-local labels between the entry point and
    290  * the break, or we need to fake it out.
    291  *
    292  * When this is defined, we add some stuff to make gdb less confused.
    293  */
    294 #define ASSIST_DEBUGGER 1
    295 
    296     .text
    297     .align  2
    298     .global dvmMterpStdRun
    299     .type   dvmMterpStdRun, %function
    300 
    301 /*
    302  * On entry:
    303  *  r0  MterpGlue* glue
    304  *
    305  * This function returns a boolean "changeInterp" value.  The return comes
    306  * via a call to dvmMterpStdBail().
    307  */
    308 dvmMterpStdRun:
    309 #define MTERP_ENTRY1 \
    310     .save {r4-r10,fp,lr}; \
    311     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
    312 #define MTERP_ENTRY2 \
    313     .pad    #4; \
    314     sub     sp, sp, #4                  @ align 64
    315 
    316     .fnstart
    317     MTERP_ENTRY1
    318     MTERP_ENTRY2
    319 
    320     /* save stack pointer, add magic word for debuggerd */
    321     str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
    322 
    323     /* set up "named" registers, figure out entry point */
    324     mov     rGLUE, r0                   @ set rGLUE
    325     ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
    326     LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
    327     adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
    328     cmp     r1, #kInterpEntryInstr      @ usual case?
    329     bne     .Lnot_instr                 @ no, handle it
    330 
    331 #if defined(WITH_JIT)
    332 .LentryInstr:
    333     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
    334     /* Entry is always a possible trace start */
    335     GET_JIT_PROF_TABLE(r0)
    336     FETCH_INST()
    337     mov     r1, #0                      @ prepare the value for the new state
    338     str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
    339     cmp     r0,#0                       @ is profiling disabled?
    340 #if !defined(WITH_SELF_VERIFICATION)
    341     bne     common_updateProfile        @ profiling is enabled
    342 #else
    343     ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
    344     beq     1f                          @ profiling is disabled
    345     ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
    346     cmp     r3, #kSVSTraceSelect        @ hot trace following?
    347     moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
    348     beq     common_selectTrace          @ go build the trace
    349     cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
    350     beq     1f                          @ intrepret the next instruction
    351     b       common_updateProfile        @ collect profiles
    352 #endif
    353 1:
    354     GET_INST_OPCODE(ip)
    355     GOTO_OPCODE(ip)
    356 #else
    357     /* start executing the instruction at rPC */
    358     FETCH_INST()                        @ load rINST from rPC
    359     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    360     GOTO_OPCODE(ip)                     @ jump to next instruction
    361 #endif
    362 
    363 .Lnot_instr:
    364     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
    365     beq     common_returnFromMethod
    366 
    367 .Lnot_return:
    368     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
    369     beq     common_exceptionThrown
    370 
    371 #if defined(WITH_JIT)
    372 .Lnot_throw:
    373     ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
    374     ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
    375     cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
    376     bne     .Lbad_arg
    377     cmp     rPC,r2
    378     bne     .LentryInstr                @ must have branched, don't resume
    379 #if defined(WITH_SELF_VERIFICATION)
    380     @ glue->entryPoint will be set in dvmSelfVerificationSaveState
    381     b       jitSVShadowRunStart         @ re-enter the translation after the
    382                                         @ single-stepped instruction
    383     @noreturn
    384 #endif
    385     mov     r1, #kInterpEntryInstr
    386     str     r1, [rGLUE, #offGlue_entryPoint]
    387     bx      r10                         @ re-enter the translation
    388 #endif
    389 
    390 .Lbad_arg:
    391     ldr     r0, strBadEntryPoint
    392     @ r1 holds value of entryPoint
    393     bl      printf
    394     bl      dvmAbort
    395     .fnend
    396 
    397 
    398     .global dvmMterpStdBail
    399     .type   dvmMterpStdBail, %function
    400 
    401 /*
    402  * Restore the stack pointer and PC from the save point established on entry.
    403  * This is essentially the same as a longjmp, but should be cheaper.  The
    404  * last instruction causes us to return to whoever called dvmMterpStdRun.
    405  *
    406  * We pushed some registers on the stack in dvmMterpStdRun, then saved
    407  * SP and LR.  Here we restore SP, restore the registers, and then restore
    408  * LR to PC.
    409  *
    410  * On entry:
    411  *  r0  MterpGlue* glue
    412  *  r1  bool changeInterp
    413  */
    414 dvmMterpStdBail:
    415     ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
    416     mov     r0, r1                          @ return the changeInterp value
    417     add     sp, sp, #4                      @ un-align 64
    418     LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
    419 
    420 
    421 /*
    422  * String references.
    423  */
    424 strBadEntryPoint:
    425     .word   .LstrBadEntryPoint
    426 
    427 
    428     .global dvmAsmInstructionStart
    429     .type   dvmAsmInstructionStart, %function
    430 dvmAsmInstructionStart = .L_OP_NOP
    431     .text
    432 
    433 /* ------------------------------ */
    434     .balign 64
    435 .L_OP_NOP: /* 0x00 */
    436 /* File: armv5te/OP_NOP.S */
    437     FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
    438     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    439     GOTO_OPCODE(ip)                     @ execute it
    440 
    441 #ifdef ASSIST_DEBUGGER
    442     /* insert fake function header to help gdb find the stack frame */
    443     .type   dalvik_inst, %function
    444 dalvik_inst:
    445     .fnstart
    446     MTERP_ENTRY1
    447     MTERP_ENTRY2
    448     .fnend
    449 #endif
    450 
    451 /* ------------------------------ */
    452     .balign 64
    453 .L_OP_MOVE: /* 0x01 */
    454 /* File: armv6t2/OP_MOVE.S */
    455     /* for move, move-object, long-to-int */
    456     /* op vA, vB */
    457     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
    458     ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
    459     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    460     GET_VREG(r2, r1)                    @ r2<- fp[B]
    461     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    462     SET_VREG(r2, r0)                    @ fp[A]<- r2
    463     GOTO_OPCODE(ip)                     @ execute next instruction
    464 
    465 /* ------------------------------ */
    466     .balign 64
    467 .L_OP_MOVE_FROM16: /* 0x02 */
    468 /* File: armv5te/OP_MOVE_FROM16.S */
    469     /* for: move/from16, move-object/from16 */
    470     /* op vAA, vBBBB */
    471     FETCH(r1, 1)                        @ r1<- BBBB
    472     mov     r0, rINST, lsr #8           @ r0<- AA
    473     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    474     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    475     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    476     SET_VREG(r2, r0)                    @ fp[AA]<- r2
    477     GOTO_OPCODE(ip)                     @ jump to next instruction
    478 
    479 /* ------------------------------ */
    480     .balign 64
    481 .L_OP_MOVE_16: /* 0x03 */
    482 /* File: armv5te/OP_MOVE_16.S */
    483     /* for: move/16, move-object/16 */
    484     /* op vAAAA, vBBBB */
    485     FETCH(r1, 2)                        @ r1<- BBBB
    486     FETCH(r0, 1)                        @ r0<- AAAA
    487     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    488     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    489     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    490     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
    491     GOTO_OPCODE(ip)                     @ jump to next instruction
    492 
    493 /* ------------------------------ */
    494     .balign 64
    495 .L_OP_MOVE_WIDE: /* 0x04 */
    496 /* File: armv6t2/OP_MOVE_WIDE.S */
    497     /* move-wide vA, vB */
    498     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    499     mov     r3, rINST, lsr #12          @ r3<- B
    500     ubfx    r2, rINST, #8, #4           @ r2<- A
    501     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
    502     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
    503     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
    504     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    506     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
    507     GOTO_OPCODE(ip)                     @ jump to next instruction
    508 
    509 /* ------------------------------ */
    510     .balign 64
    511 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
    512 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
    513     /* move-wide/from16 vAA, vBBBB */
    514     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    515     FETCH(r3, 1)                        @ r3<- BBBB
    516     mov     r2, rINST, lsr #8           @ r2<- AA
    517     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
    518     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
    519     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
    520     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    521     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    522     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
    523     GOTO_OPCODE(ip)                     @ jump to next instruction
    524 
    525 /* ------------------------------ */
    526     .balign 64
    527 .L_OP_MOVE_WIDE_16: /* 0x06 */
    528 /* File: armv5te/OP_MOVE_WIDE_16.S */
    529     /* move-wide/16 vAAAA, vBBBB */
    530     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    531     FETCH(r3, 2)                        @ r3<- BBBB
    532     FETCH(r2, 1)                        @ r2<- AAAA
    533     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
    534     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
    535     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
    536     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    537     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    538     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
    539     GOTO_OPCODE(ip)                     @ jump to next instruction
    540 
    541 /* ------------------------------ */
    542     .balign 64
    543 .L_OP_MOVE_OBJECT: /* 0x07 */
    544 /* File: armv5te/OP_MOVE_OBJECT.S */
    545 /* File: armv5te/OP_MOVE.S */
    546     /* for move, move-object, long-to-int */
    547     /* op vA, vB */
    548     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
    549     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
    550     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    551     GET_VREG(r2, r1)                    @ r2<- fp[B]
    552     and     r0, r0, #15
    553     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    554     SET_VREG(r2, r0)                    @ fp[A]<- r2
    555     GOTO_OPCODE(ip)                     @ execute next instruction
    556 
    557 
    558 /* ------------------------------ */
    559     .balign 64
    560 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
    561 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
    562 /* File: armv5te/OP_MOVE_FROM16.S */
    563     /* for: move/from16, move-object/from16 */
    564     /* op vAA, vBBBB */
    565     FETCH(r1, 1)                        @ r1<- BBBB
    566     mov     r0, rINST, lsr #8           @ r0<- AA
    567     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    568     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    569     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    570     SET_VREG(r2, r0)                    @ fp[AA]<- r2
    571     GOTO_OPCODE(ip)                     @ jump to next instruction
    572 
    573 
    574 /* ------------------------------ */
    575     .balign 64
    576 .L_OP_MOVE_OBJECT_16: /* 0x09 */
    577 /* File: armv5te/OP_MOVE_OBJECT_16.S */
    578 /* File: armv5te/OP_MOVE_16.S */
    579     /* for: move/16, move-object/16 */
    580     /* op vAAAA, vBBBB */
    581     FETCH(r1, 2)                        @ r1<- BBBB
    582     FETCH(r0, 1)                        @ r0<- AAAA
    583     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    584     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    585     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    586     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
    587     GOTO_OPCODE(ip)                     @ jump to next instruction
    588 
    589 
    590 /* ------------------------------ */
    591     .balign 64
    592 .L_OP_MOVE_RESULT: /* 0x0a */
    593 /* File: armv5te/OP_MOVE_RESULT.S */
    594     /* for: move-result, move-result-object */
    595     /* op vAA */
    596     mov     r2, rINST, lsr #8           @ r2<- AA
    597     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    598     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
    599     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    600     SET_VREG(r0, r2)                    @ fp[AA]<- r0
    601     GOTO_OPCODE(ip)                     @ jump to next instruction
    602 
    603 /* ------------------------------ */
    604     .balign 64
    605 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
    606 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
    607     /* move-result-wide vAA */
    608     mov     r2, rINST, lsr #8           @ r2<- AA
    609     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
    610     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
    611     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
    612     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    613     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    614     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
    615     GOTO_OPCODE(ip)                     @ jump to next instruction
    616 
    617 /* ------------------------------ */
    618     .balign 64
    619 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
    620 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
    621 /* File: armv5te/OP_MOVE_RESULT.S */
    622     /* for: move-result, move-result-object */
    623     /* op vAA */
    624     mov     r2, rINST, lsr #8           @ r2<- AA
    625     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    626     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
    627     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    628     SET_VREG(r0, r2)                    @ fp[AA]<- r0
    629     GOTO_OPCODE(ip)                     @ jump to next instruction
    630 
    631 
    632 /* ------------------------------ */
    633     .balign 64
    634 .L_OP_MOVE_EXCEPTION: /* 0x0d */
    635 /* File: armv5te/OP_MOVE_EXCEPTION.S */
    636     /* move-exception vAA */
    637     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    638     mov     r2, rINST, lsr #8           @ r2<- AA
    639     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
    640     mov     r1, #0                      @ r1<- 0
    641     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    642     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
    643     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    644     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
    645     GOTO_OPCODE(ip)                     @ jump to next instruction
    646 
    647 /* ------------------------------ */
    648     .balign 64
    649 .L_OP_RETURN_VOID: /* 0x0e */
    650 /* File: armv5te/OP_RETURN_VOID.S */
    651     b       common_returnFromMethod
    652 
    653 /* ------------------------------ */
    654     .balign 64
    655 .L_OP_RETURN: /* 0x0f */
    656 /* File: armv5te/OP_RETURN.S */
    657     /*
    658      * Return a 32-bit value.  Copies the return value into the "glue"
    659      * structure, then jumps to the return handler.
    660      *
    661      * for: return, return-object
    662      */
    663     /* op vAA */
    664     mov     r2, rINST, lsr #8           @ r2<- AA
    665     GET_VREG(r0, r2)                    @ r0<- vAA
    666     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
    667     b       common_returnFromMethod
    668 
    669 /* ------------------------------ */
    670     .balign 64
    671 .L_OP_RETURN_WIDE: /* 0x10 */
    672 /* File: armv5te/OP_RETURN_WIDE.S */
    673     /*
    674      * Return a 64-bit value.  Copies the return value into the "glue"
    675      * structure, then jumps to the return handler.
    676      */
    677     /* return-wide vAA */
    678     mov     r2, rINST, lsr #8           @ r2<- AA
    679     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
    680     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
    681     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
    682     stmia   r3, {r0-r1}                 @ retval<- r0/r1
    683     b       common_returnFromMethod
    684 
    685 /* ------------------------------ */
    686     .balign 64
    687 .L_OP_RETURN_OBJECT: /* 0x11 */
    688 /* File: armv5te/OP_RETURN_OBJECT.S */
    689 /* File: armv5te/OP_RETURN.S */
    690     /*
    691      * Return a 32-bit value.  Copies the return value into the "glue"
    692      * structure, then jumps to the return handler.
    693      *
    694      * for: return, return-object
    695      */
    696     /* op vAA */
    697     mov     r2, rINST, lsr #8           @ r2<- AA
    698     GET_VREG(r0, r2)                    @ r0<- vAA
    699     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
    700     b       common_returnFromMethod
    701 
    702 
    703 /* ------------------------------ */
    704     .balign 64
    705 .L_OP_CONST_4: /* 0x12 */
    706 /* File: armv6t2/OP_CONST_4.S */
    707     /* const/4 vA, #+B */
    708     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
    709     ubfx    r0, rINST, #8, #4           @ r0<- A
    710     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    711     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
    712     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    713     SET_VREG(r1, r0)                    @ fp[A]<- r1
    714     GOTO_OPCODE(ip)                     @ execute next instruction
    715 
    716 /* ------------------------------ */
    717     .balign 64
    718 .L_OP_CONST_16: /* 0x13 */
    719 /* File: armv5te/OP_CONST_16.S */
    720     /* const/16 vAA, #+BBBB */
    721     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
    722     mov     r3, rINST, lsr #8           @ r3<- AA
    723     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    724     SET_VREG(r0, r3)                    @ vAA<- r0
    725     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    726     GOTO_OPCODE(ip)                     @ jump to next instruction
    727 
    728 /* ------------------------------ */
    729     .balign 64
    730 .L_OP_CONST: /* 0x14 */
    731 /* File: armv5te/OP_CONST.S */
    732     /* const vAA, #+BBBBbbbb */
    733     mov     r3, rINST, lsr #8           @ r3<- AA
    734     FETCH(r0, 1)                        @ r0<- bbbb (low)
    735     FETCH(r1, 2)                        @ r1<- BBBB (high)
    736     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    737     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
    738     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    739     SET_VREG(r0, r3)                    @ vAA<- r0
    740     GOTO_OPCODE(ip)                     @ jump to next instruction
    741 
    742 /* ------------------------------ */
    743     .balign 64
    744 .L_OP_CONST_HIGH16: /* 0x15 */
    745 /* File: armv5te/OP_CONST_HIGH16.S */
    746     /* const/high16 vAA, #+BBBB0000 */
    747     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
    748     mov     r3, rINST, lsr #8           @ r3<- AA
    749     mov     r0, r0, lsl #16             @ r0<- BBBB0000
    750     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    751     SET_VREG(r0, r3)                    @ vAA<- r0
    752     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    753     GOTO_OPCODE(ip)                     @ jump to next instruction
    754 
    755 /* ------------------------------ */
    756     .balign 64
    757 .L_OP_CONST_WIDE_16: /* 0x16 */
    758 /* File: armv5te/OP_CONST_WIDE_16.S */
    759     /* const-wide/16 vAA, #+BBBB */
    760     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
    761     mov     r3, rINST, lsr #8           @ r3<- AA
    762     mov     r1, r0, asr #31             @ r1<- ssssssss
    763     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    764     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
    765     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    766     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
    767     GOTO_OPCODE(ip)                     @ jump to next instruction
    768 
    769 /* ------------------------------ */
    770     .balign 64
    771 .L_OP_CONST_WIDE_32: /* 0x17 */
    772 /* File: armv5te/OP_CONST_WIDE_32.S */
    773     /* const-wide/32 vAA, #+BBBBbbbb */
    774     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
    775     mov     r3, rINST, lsr #8           @ r3<- AA
    776     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
    777     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    778     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
    779     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
    780     mov     r1, r0, asr #31             @ r1<- ssssssss
    781     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    782     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
    783     GOTO_OPCODE(ip)                     @ jump to next instruction
    784 
    785 /* ------------------------------ */
    786     .balign 64
    787 .L_OP_CONST_WIDE: /* 0x18 */
    788 /* File: armv5te/OP_CONST_WIDE.S */
    789     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
    790     FETCH(r0, 1)                        @ r0<- bbbb (low)
    791     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
    792     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
    793     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
    794     FETCH(r3, 4)                        @ r3<- HHHH (high)
    795     mov     r9, rINST, lsr #8           @ r9<- AA
    796     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
    797     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
    798     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
    799     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    800     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
    801     GOTO_OPCODE(ip)                     @ jump to next instruction
    802 
    803 /* ------------------------------ */
    804     .balign 64
    805 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
    806 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
    807     /* const-wide/high16 vAA, #+BBBB000000000000 */
    808     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
    809     mov     r3, rINST, lsr #8           @ r3<- AA
    810     mov     r0, #0                      @ r0<- 00000000
    811     mov     r1, r1, lsl #16             @ r1<- BBBB0000
    812     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    813     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
    814     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    815     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
    816     GOTO_OPCODE(ip)                     @ jump to next instruction
    817 
    818 /* ------------------------------ */
    819     .balign 64
    820 .L_OP_CONST_STRING: /* 0x1a */
    821 /* File: armv5te/OP_CONST_STRING.S */
    822     /* const/string vAA, String@BBBB */
    823     FETCH(r1, 1)                        @ r1<- BBBB
    824     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
    825     mov     r9, rINST, lsr #8           @ r9<- AA
    826     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
    827     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
    828     cmp     r0, #0                      @ not yet resolved?
    829     beq     .LOP_CONST_STRING_resolve
    830     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    831     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    832     SET_VREG(r0, r9)                    @ vAA<- r0
    833     GOTO_OPCODE(ip)                     @ jump to next instruction
    834 
    835 /* ------------------------------ */
    836     .balign 64
    837 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
    838 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
    839     /* const/string vAA, String@BBBBBBBB */
    840     FETCH(r0, 1)                        @ r0<- bbbb (low)
    841     FETCH(r1, 2)                        @ r1<- BBBB (high)
    842     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
    843     mov     r9, rINST, lsr #8           @ r9<- AA
    844     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
    845     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
    846     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
    847     cmp     r0, #0
    848     beq     .LOP_CONST_STRING_JUMBO_resolve
    849     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    850     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    851     SET_VREG(r0, r9)                    @ vAA<- r0
    852     GOTO_OPCODE(ip)                     @ jump to next instruction
    853 
    854 /* ------------------------------ */
    855     .balign 64
    856 .L_OP_CONST_CLASS: /* 0x1c */
    857 /* File: armv5te/OP_CONST_CLASS.S */
    858     /* const/class vAA, Class@BBBB */
    859     FETCH(r1, 1)                        @ r1<- BBBB
    860     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
    861     mov     r9, rINST, lsr #8           @ r9<- AA
    862     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
    863     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
    864     cmp     r0, #0                      @ not yet resolved?
    865     beq     .LOP_CONST_CLASS_resolve
    866     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    867     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    868     SET_VREG(r0, r9)                    @ vAA<- r0
    869     GOTO_OPCODE(ip)                     @ jump to next instruction
    870 
    871 /* ------------------------------ */
    872     .balign 64
    873 .L_OP_MONITOR_ENTER: /* 0x1d */
    874 /* File: armv5te/OP_MONITOR_ENTER.S */
    875     /*
    876      * Synchronize on an object.
    877      */
    878     /* monitor-enter vAA */
    879     mov     r2, rINST, lsr #8           @ r2<- AA
    880     GET_VREG(r1, r2)                    @ r1<- vAA (object)
    881     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    882     cmp     r1, #0                      @ null object?
    883     EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
    884     beq     common_errNullObject        @ null object, throw an exception
    885     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    886     bl      dvmLockObject               @ call(self, obj)
    887 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
    888     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    889     ldr     r1, [r0, #offThread_exception] @ check for exception
    890     cmp     r1, #0
    891     bne     common_exceptionThrown      @ exception raised, bail out
    892 #endif
    893     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    894     GOTO_OPCODE(ip)                     @ jump to next instruction
    895 
    896 /* ------------------------------ */
    897     .balign 64
    898 .L_OP_MONITOR_EXIT: /* 0x1e */
    899 /* File: armv5te/OP_MONITOR_EXIT.S */
    900     /*
    901      * Unlock an object.
    902      *
    903      * Exceptions that occur when unlocking a monitor need to appear as
    904      * if they happened at the following instruction.  See the Dalvik
    905      * instruction spec.
    906      */
    907     /* monitor-exit vAA */
    908     mov     r2, rINST, lsr #8           @ r2<- AA
    909     EXPORT_PC()                         @ before fetch: export the PC
    910     GET_VREG(r1, r2)                    @ r1<- vAA (object)
    911     cmp     r1, #0                      @ null object?
    912     beq     1f                          @ yes
    913     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    914     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
    915     cmp     r0, #0                      @ failed?
    916     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
    917     beq     common_exceptionThrown      @ yes, exception is pending
    918     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    919     GOTO_OPCODE(ip)                     @ jump to next instruction
    920 1:
    921     FETCH_ADVANCE_INST(1)               @ advance before throw
    922     b      common_errNullObject
    923 
    924 /* ------------------------------ */
    925     .balign 64
    926 .L_OP_CHECK_CAST: /* 0x1f */
    927 /* File: armv5te/OP_CHECK_CAST.S */
    928     /*
    929      * Check to see if a cast from one class to another is allowed.
    930      */
    931     /* check-cast vAA, class@BBBB */
    932     mov     r3, rINST, lsr #8           @ r3<- AA
    933     FETCH(r2, 1)                        @ r2<- BBBB
    934     GET_VREG(r9, r3)                    @ r9<- object
    935     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
    936     cmp     r9, #0                      @ is object null?
    937     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
    938     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
    939     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
    940     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
    941     cmp     r1, #0                      @ have we resolved this before?
    942     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
    943 .LOP_CHECK_CAST_resolved:
    944     cmp     r0, r1                      @ same class (trivial success)?
    945     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
    946 .LOP_CHECK_CAST_okay:
    947     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    948     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    949     GOTO_OPCODE(ip)                     @ jump to next instruction
    950 
    951 /* ------------------------------ */
    952     .balign 64
    953 .L_OP_INSTANCE_OF: /* 0x20 */
    954 /* File: armv5te/OP_INSTANCE_OF.S */
    955     /*
    956      * Check to see if an object reference is an instance of a class.
    957      *
    958      * Most common situation is a non-null object, being compared against
    959      * an already-resolved class.
    960      */
    961     /* instance-of vA, vB, class@CCCC */
    962     mov     r3, rINST, lsr #12          @ r3<- B
    963     mov     r9, rINST, lsr #8           @ r9<- A+
    964     GET_VREG(r0, r3)                    @ r0<- vB (object)
    965     and     r9, r9, #15                 @ r9<- A
    966     cmp     r0, #0                      @ is object null?
    967     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
    968     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
    969     FETCH(r3, 1)                        @ r3<- CCCC
    970     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
    971     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
    972     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
    973     cmp     r1, #0                      @ have we resolved this before?
    974     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
    975 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
    976     cmp     r0, r1                      @ same class (trivial success)?
    977     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
    978     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
    979 
    980 /* ------------------------------ */
    981     .balign 64
    982 .L_OP_ARRAY_LENGTH: /* 0x21 */
    983 /* File: armv6t2/OP_ARRAY_LENGTH.S */
    984     /*
    985      * Return the length of an array.
    986      */
    987     mov     r1, rINST, lsr #12          @ r1<- B
    988     ubfx    r2, rINST, #8, #4           @ r2<- A
    989     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
    990     cmp     r0, #0                      @ is object null?
    991     beq     common_errNullObject        @ yup, fail
    992     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    993     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
    994     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    995     SET_VREG(r3, r2)                    @ vB<- length
    996     GOTO_OPCODE(ip)                     @ jump to next instruction
    997 
    998 /* ------------------------------ */
    999     .balign 64
   1000 .L_OP_NEW_INSTANCE: /* 0x22 */
   1001 /* File: armv5te/OP_NEW_INSTANCE.S */
   1002     /*
   1003      * Create a new instance of a class.
   1004      */
   1005     /* new-instance vAA, class@BBBB */
   1006     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1007     FETCH(r1, 1)                        @ r1<- BBBB
   1008     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1009     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
   1010     EXPORT_PC()                         @ req'd for init, resolve, alloc
   1011     cmp     r0, #0                      @ already resolved?
   1012     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
   1013 .LOP_NEW_INSTANCE_resolved:   @ r0=class
   1014     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
   1015     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
   1016     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
   1017 .LOP_NEW_INSTANCE_initialized: @ r0=class
   1018     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
   1019     bl      dvmAllocObject              @ r0<- new object
   1020     b       .LOP_NEW_INSTANCE_finish          @ continue
   1021 
   1022 /* ------------------------------ */
   1023     .balign 64
   1024 .L_OP_NEW_ARRAY: /* 0x23 */
   1025 /* File: armv5te/OP_NEW_ARRAY.S */
   1026     /*
   1027      * Allocate an array of objects, specified with the array class
   1028      * and a count.
   1029      *
   1030      * The verifier guarantees that this is an array class, so we don't
   1031      * check for it here.
   1032      */
   1033     /* new-array vA, vB, class@CCCC */
   1034     mov     r0, rINST, lsr #12          @ r0<- B
   1035     FETCH(r2, 1)                        @ r2<- CCCC
   1036     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1037     GET_VREG(r1, r0)                    @ r1<- vB (array length)
   1038     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1039     cmp     r1, #0                      @ check length
   1040     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
   1041     bmi     common_errNegativeArraySize @ negative length, bail
   1042     cmp     r0, #0                      @ already resolved?
   1043     EXPORT_PC()                         @ req'd for resolve, alloc
   1044     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
   1045     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
   1046 
   1047 /* ------------------------------ */
   1048     .balign 64
   1049 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
   1050 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
   1051     /*
   1052      * Create a new array with elements filled from registers.
   1053      *
   1054      * for: filled-new-array, filled-new-array/range
   1055      */
   1056     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   1057     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
   1058     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1059     FETCH(r1, 1)                        @ r1<- BBBB
   1060     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1061     EXPORT_PC()                         @ need for resolve and alloc
   1062     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
   1063     mov     r10, rINST, lsr #8          @ r10<- AA or BA
   1064     cmp     r0, #0                      @ already resolved?
   1065     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
   1066 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   1067     mov     r2, #0                      @ r2<- false
   1068     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   1069     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   1070     cmp     r0, #0                      @ got null?
   1071     beq     common_exceptionThrown      @ yes, handle exception
   1072     b       .LOP_FILLED_NEW_ARRAY_continue
   1073 
   1074 /* ------------------------------ */
   1075     .balign 64
   1076 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
   1077 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
   1078 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
   1079     /*
   1080      * Create a new array with elements filled from registers.
   1081      *
   1082      * for: filled-new-array, filled-new-array/range
   1083      */
   1084     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   1085     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
   1086     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1087     FETCH(r1, 1)                        @ r1<- BBBB
   1088     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1089     EXPORT_PC()                         @ need for resolve and alloc
   1090     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
   1091     mov     r10, rINST, lsr #8          @ r10<- AA or BA
   1092     cmp     r0, #0                      @ already resolved?
   1093     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
   1094 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   1095     mov     r2, #0                      @ r2<- false
   1096     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   1097     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   1098     cmp     r0, #0                      @ got null?
   1099     beq     common_exceptionThrown      @ yes, handle exception
   1100     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
   1101 
   1102 
   1103 /* ------------------------------ */
   1104     .balign 64
   1105 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
   1106 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
   1107     /* fill-array-data vAA, +BBBBBBBB */
   1108     FETCH(r0, 1)                        @ r0<- bbbb (lo)
   1109     FETCH(r1, 2)                        @ r1<- BBBB (hi)
   1110     mov     r3, rINST, lsr #8           @ r3<- AA
   1111     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
   1112     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
   1113     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
   1114     EXPORT_PC();
   1115     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
   1116     cmp     r0, #0                      @ 0 means an exception is thrown
   1117     beq     common_exceptionThrown      @ has exception
   1118     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   1119     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1120     GOTO_OPCODE(ip)                     @ jump to next instruction
   1121 
   1122 /* ------------------------------ */
   1123     .balign 64
   1124 .L_OP_THROW: /* 0x27 */
   1125 /* File: armv5te/OP_THROW.S */
   1126     /*
   1127      * Throw an exception object in the current thread.
   1128      */
   1129     /* throw vAA */
   1130     mov     r2, rINST, lsr #8           @ r2<- AA
   1131     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
   1132     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   1133     EXPORT_PC()                         @ exception handler can throw
   1134     cmp     r1, #0                      @ null object?
   1135     beq     common_errNullObject        @ yes, throw an NPE instead
   1136     @ bypass dvmSetException, just store it
   1137     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
   1138     b       common_exceptionThrown
   1139 
   1140 /* ------------------------------ */
   1141     .balign 64
   1142 .L_OP_GOTO: /* 0x28 */
   1143 /* File: armv5te/OP_GOTO.S */
   1144     /*
   1145      * Unconditional branch, 8-bit offset.
   1146      *
   1147      * The branch distance is a signed code-unit offset, which we need to
   1148      * double to get a byte offset.
   1149      */
   1150     /* goto +AA */
   1151     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
   1152     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
   1153     mov     r9, r9, lsl #1              @ r9<- byte offset
   1154     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1155 #if defined(WITH_JIT)
   1156     GET_JIT_PROF_TABLE(r0)
   1157     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1158     cmp     r0,#0
   1159     bne     common_updateProfile
   1160     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1161     GOTO_OPCODE(ip)                     @ jump to next instruction
   1162 #else
   1163     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1164     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1165     GOTO_OPCODE(ip)                     @ jump to next instruction
   1166 #endif
   1167 
   1168 /* ------------------------------ */
   1169     .balign 64
   1170 .L_OP_GOTO_16: /* 0x29 */
   1171 /* File: armv5te/OP_GOTO_16.S */
   1172     /*
   1173      * Unconditional branch, 16-bit offset.
   1174      *
   1175      * The branch distance is a signed code-unit offset, which we need to
   1176      * double to get a byte offset.
   1177      */
   1178     /* goto/16 +AAAA */
   1179     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
   1180     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
   1181     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1182 #if defined(WITH_JIT)
   1183     GET_JIT_PROF_TABLE(r0)
   1184     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1185     cmp     r0,#0
   1186     bne     common_updateProfile
   1187     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1188     GOTO_OPCODE(ip)                     @ jump to next instruction
   1189 #else
   1190     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1191     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1192     GOTO_OPCODE(ip)                     @ jump to next instruction
   1193 #endif
   1194 
   1195 /* ------------------------------ */
   1196     .balign 64
   1197 .L_OP_GOTO_32: /* 0x2a */
   1198 /* File: armv5te/OP_GOTO_32.S */
   1199     /*
   1200      * Unconditional branch, 32-bit offset.
   1201      *
   1202      * The branch distance is a signed code-unit offset, which we need to
   1203      * double to get a byte offset.
   1204      *
   1205      * Unlike most opcodes, this one is allowed to branch to itself, so
   1206      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
   1207      * instruction doesn't affect the V flag, so we need to clear it
   1208      * explicitly.
   1209      */
   1210     /* goto/32 +AAAAAAAA */
   1211     FETCH(r0, 1)                        @ r0<- aaaa (lo)
   1212     FETCH(r1, 2)                        @ r1<- AAAA (hi)
   1213     cmp     ip, ip                      @ (clear V flag during stall)
   1214     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
   1215     mov     r9, r0, asl #1              @ r9<- byte offset
   1216     ble     common_backwardBranch       @ backward branch, do periodic checks
   1217 #if defined(WITH_JIT)
   1218     GET_JIT_PROF_TABLE(r0)
   1219     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1220     cmp     r0,#0
   1221     bne     common_updateProfile
   1222     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1223     GOTO_OPCODE(ip)                     @ jump to next instruction
   1224 #else
   1225     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1226     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1227     GOTO_OPCODE(ip)                     @ jump to next instruction
   1228 #endif
   1229 
   1230 /* ------------------------------ */
   1231     .balign 64
   1232 .L_OP_PACKED_SWITCH: /* 0x2b */
   1233 /* File: armv5te/OP_PACKED_SWITCH.S */
   1234     /*
   1235      * Handle a packed-switch or sparse-switch instruction.  In both cases
   1236      * we decode it and hand it off to a helper function.
   1237      *
   1238      * We don't really expect backward branches in a switch statement, but
   1239      * they're perfectly legal, so we check for them here.
   1240      *
   1241      * for: packed-switch, sparse-switch
   1242      */
   1243     /* op vAA, +BBBB */
   1244     FETCH(r0, 1)                        @ r0<- bbbb (lo)
   1245     FETCH(r1, 2)                        @ r1<- BBBB (hi)
   1246     mov     r3, rINST, lsr #8           @ r3<- AA
   1247     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
   1248     GET_VREG(r1, r3)                    @ r1<- vAA
   1249     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
   1250     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
   1251     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
   1252     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1253     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
   1254 #if defined(WITH_JIT)
   1255     GET_JIT_PROF_TABLE(r0)
   1256     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1257     cmp     r0,#0
   1258     bne     common_updateProfile
   1259     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1260     GOTO_OPCODE(ip)                     @ jump to next instruction
   1261 #else
   1262     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1263     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1264     GOTO_OPCODE(ip)                     @ jump to next instruction
   1265 #endif
   1266 
   1267 /* ------------------------------ */
   1268     .balign 64
   1269 .L_OP_SPARSE_SWITCH: /* 0x2c */
   1270 /* File: armv5te/OP_SPARSE_SWITCH.S */
   1271 /* File: armv5te/OP_PACKED_SWITCH.S */
   1272     /*
   1273      * Handle a packed-switch or sparse-switch instruction.  In both cases
   1274      * we decode it and hand it off to a helper function.
   1275      *
   1276      * We don't really expect backward branches in a switch statement, but
   1277      * they're perfectly legal, so we check for them here.
   1278      *
   1279      * for: packed-switch, sparse-switch
   1280      */
   1281     /* op vAA, +BBBB */
   1282     FETCH(r0, 1)                        @ r0<- bbbb (lo)
   1283     FETCH(r1, 2)                        @ r1<- BBBB (hi)
   1284     mov     r3, rINST, lsr #8           @ r3<- AA
   1285     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
   1286     GET_VREG(r1, r3)                    @ r1<- vAA
   1287     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
   1288     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
   1289     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
   1290     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1291     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
   1292 #if defined(WITH_JIT)
   1293     GET_JIT_PROF_TABLE(r0)
   1294     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1295     cmp     r0,#0
   1296     bne     common_updateProfile
   1297     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1298     GOTO_OPCODE(ip)                     @ jump to next instruction
   1299 #else
   1300     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1301     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1302     GOTO_OPCODE(ip)                     @ jump to next instruction
   1303 #endif
   1304 
   1305 
   1306 /* ------------------------------ */
   1307     .balign 64
   1308 .L_OP_CMPL_FLOAT: /* 0x2d */
   1309 /* File: arm-vfp/OP_CMPL_FLOAT.S */
   1310     /*
   1311      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1312      * destination register based on the results of the comparison.
   1313      *
   1314      * int compare(x, y) {
   1315      *     if (x == y) {
   1316      *         return 0;
   1317      *     } else if (x > y) {
   1318      *         return 1;
   1319      *     } else if (x < y) {
   1320      *         return -1;
   1321      *     } else {
   1322      *         return -1;
   1323      *     }
   1324      * }
   1325      */
   1326     /* op vAA, vBB, vCC */
   1327     FETCH(r0, 1)                        @ r0<- CCBB
   1328     mov     r9, rINST, lsr #8           @ r9<- AA
   1329     and     r2, r0, #255                @ r2<- BB
   1330     mov     r3, r0, lsr #8              @ r3<- CC
   1331     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1332     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1333     flds    s0, [r2]                    @ s0<- vBB
   1334     flds    s1, [r3]                    @ s1<- vCC
   1335     fcmpes  s0, s1                      @ compare (vBB, vCC)
   1336     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1337     mvn     r0, #0                      @ r0<- -1 (default)
   1338     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1339     fmstat                              @ export status flags
   1340     movgt   r0, #1                      @ (greater than) r1<- 1
   1341     moveq   r0, #0                      @ (equal) r1<- 0
   1342     b       .LOP_CMPL_FLOAT_finish          @ argh
   1343 
   1344 
   1345 /* ------------------------------ */
   1346     .balign 64
   1347 .L_OP_CMPG_FLOAT: /* 0x2e */
   1348 /* File: arm-vfp/OP_CMPG_FLOAT.S */
   1349     /*
   1350      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1351      * destination register based on the results of the comparison.
   1352      *
   1353      * int compare(x, y) {
   1354      *     if (x == y) {
   1355      *         return 0;
   1356      *     } else if (x < y) {
   1357      *         return -1;
   1358      *     } else if (x > y) {
   1359      *         return 1;
   1360      *     } else {
   1361      *         return 1;
   1362      *     }
   1363      * }
   1364      */
   1365     /* op vAA, vBB, vCC */
   1366     FETCH(r0, 1)                        @ r0<- CCBB
   1367     mov     r9, rINST, lsr #8           @ r9<- AA
   1368     and     r2, r0, #255                @ r2<- BB
   1369     mov     r3, r0, lsr #8              @ r3<- CC
   1370     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1371     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1372     flds    s0, [r2]                    @ s0<- vBB
   1373     flds    s1, [r3]                    @ s1<- vCC
   1374     fcmpes  s0, s1                      @ compare (vBB, vCC)
   1375     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1376     mov     r0, #1                      @ r0<- 1 (default)
   1377     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1378     fmstat                              @ export status flags
   1379     mvnmi   r0, #0                      @ (less than) r1<- -1
   1380     moveq   r0, #0                      @ (equal) r1<- 0
   1381     b       .LOP_CMPG_FLOAT_finish          @ argh
   1382 
   1383 
   1384 /* ------------------------------ */
   1385     .balign 64
   1386 .L_OP_CMPL_DOUBLE: /* 0x2f */
   1387 /* File: arm-vfp/OP_CMPL_DOUBLE.S */
   1388     /*
   1389      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1390      * destination register based on the results of the comparison.
   1391      *
   1392      * int compare(x, y) {
   1393      *     if (x == y) {
   1394      *         return 0;
   1395      *     } else if (x > y) {
   1396      *         return 1;
   1397      *     } else if (x < y) {
   1398      *         return -1;
   1399      *     } else {
   1400      *         return -1;
   1401      *     }
   1402      * }
   1403      */
   1404     /* op vAA, vBB, vCC */
   1405     FETCH(r0, 1)                        @ r0<- CCBB
   1406     mov     r9, rINST, lsr #8           @ r9<- AA
   1407     and     r2, r0, #255                @ r2<- BB
   1408     mov     r3, r0, lsr #8              @ r3<- CC
   1409     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1410     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1411     fldd    d0, [r2]                    @ d0<- vBB
   1412     fldd    d1, [r3]                    @ d1<- vCC
   1413     fcmped  d0, d1                      @ compare (vBB, vCC)
   1414     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1415     mvn     r0, #0                      @ r0<- -1 (default)
   1416     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1417     fmstat                              @ export status flags
   1418     movgt   r0, #1                      @ (greater than) r1<- 1
   1419     moveq   r0, #0                      @ (equal) r1<- 0
   1420     b       .LOP_CMPL_DOUBLE_finish          @ argh
   1421 
   1422 
   1423 /* ------------------------------ */
   1424     .balign 64
   1425 .L_OP_CMPG_DOUBLE: /* 0x30 */
   1426 /* File: arm-vfp/OP_CMPG_DOUBLE.S */
   1427     /*
   1428      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1429      * destination register based on the results of the comparison.
   1430      *
   1431      * int compare(x, y) {
   1432      *     if (x == y) {
   1433      *         return 0;
   1434      *     } else if (x < y) {
   1435      *         return -1;
   1436      *     } else if (x > y) {
   1437      *         return 1;
   1438      *     } else {
   1439      *         return 1;
   1440      *     }
   1441      * }
   1442      */
   1443     /* op vAA, vBB, vCC */
   1444     FETCH(r0, 1)                        @ r0<- CCBB
   1445     mov     r9, rINST, lsr #8           @ r9<- AA
   1446     and     r2, r0, #255                @ r2<- BB
   1447     mov     r3, r0, lsr #8              @ r3<- CC
   1448     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1449     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1450     fldd    d0, [r2]                    @ d0<- vBB
   1451     fldd    d1, [r3]                    @ d1<- vCC
   1452     fcmped  d0, d1                      @ compare (vBB, vCC)
   1453     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1454     mov     r0, #1                      @ r0<- 1 (default)
   1455     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1456     fmstat                              @ export status flags
   1457     mvnmi   r0, #0                      @ (less than) r1<- -1
   1458     moveq   r0, #0                      @ (equal) r1<- 0
   1459     b       .LOP_CMPG_DOUBLE_finish          @ argh
   1460 
   1461 
   1462 /* ------------------------------ */
   1463     .balign 64
   1464 .L_OP_CMP_LONG: /* 0x31 */
   1465 /* File: armv5te/OP_CMP_LONG.S */
   1466     /*
   1467      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
   1468      * register based on the results of the comparison.
   1469      *
   1470      * We load the full values with LDM, but in practice many values could
   1471      * be resolved by only looking at the high word.  This could be made
   1472      * faster or slower by splitting the LDM into a pair of LDRs.
   1473      *
   1474      * If we just wanted to set condition flags, we could do this:
   1475      *  subs    ip, r0, r2
   1476      *  sbcs    ip, r1, r3
   1477      *  subeqs  ip, r0, r2
   1478      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
   1479      * integer value, which we can do with 2 conditional mov/mvn instructions
   1480      * (set 1, set -1; if they're equal we already have 0 in ip), giving
   1481      * us a constant 5-cycle path plus a branch at the end to the
   1482      * instruction epilogue code.  The multi-compare approach below needs
   1483      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
   1484      * in the worst case (the 64-bit values are equal).
   1485      */
   1486     /* cmp-long vAA, vBB, vCC */
   1487     FETCH(r0, 1)                        @ r0<- CCBB
   1488     mov     r9, rINST, lsr #8           @ r9<- AA
   1489     and     r2, r0, #255                @ r2<- BB
   1490     mov     r3, r0, lsr #8              @ r3<- CC
   1491     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   1492     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   1493     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   1494     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   1495     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
   1496     blt     .LOP_CMP_LONG_less            @ signed compare on high part
   1497     bgt     .LOP_CMP_LONG_greater
   1498     subs    r1, r0, r2                  @ r1<- r0 - r2
   1499     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
   1500     bne     .LOP_CMP_LONG_less
   1501     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
   1502 
   1503 /* ------------------------------ */
   1504     .balign 64
   1505 .L_OP_IF_EQ: /* 0x32 */
   1506 /* File: armv6t2/OP_IF_EQ.S */
   1507 /* File: armv6t2/bincmp.S */
   1508     /*
   1509      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1510      * fragment that specifies the *reverse* comparison to perform, e.g.
   1511      * for "if-le" you would use "gt".
   1512      *
   1513      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1514      */
   1515     /* if-cmp vA, vB, +CCCC */
   1516     mov     r1, rINST, lsr #12          @ r1<- B
   1517     ubfx    r0, rINST, #8, #4           @ r0<- A
   1518     GET_VREG(r3, r1)                    @ r3<- vB
   1519     GET_VREG(r2, r0)                    @ r2<- vA
   1520     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1521     cmp     r2, r3                      @ compare (vA, vB)
   1522     bne  1f                      @ branch to 1 if comparison failed
   1523     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1524     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1525     bmi     common_backwardBranch       @ yes, do periodic checks
   1526 1:
   1527 #if defined(WITH_JIT)
   1528     GET_JIT_PROF_TABLE(r0)
   1529     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1530     b        common_testUpdateProfile
   1531 #else
   1532     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1533     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1534     GOTO_OPCODE(ip)                     @ jump to next instruction
   1535 #endif
   1536 
   1537 
   1538 /* ------------------------------ */
   1539     .balign 64
   1540 .L_OP_IF_NE: /* 0x33 */
   1541 /* File: armv6t2/OP_IF_NE.S */
   1542 /* File: armv6t2/bincmp.S */
   1543     /*
   1544      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1545      * fragment that specifies the *reverse* comparison to perform, e.g.
   1546      * for "if-le" you would use "gt".
   1547      *
   1548      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1549      */
   1550     /* if-cmp vA, vB, +CCCC */
   1551     mov     r1, rINST, lsr #12          @ r1<- B
   1552     ubfx    r0, rINST, #8, #4           @ r0<- A
   1553     GET_VREG(r3, r1)                    @ r3<- vB
   1554     GET_VREG(r2, r0)                    @ r2<- vA
   1555     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1556     cmp     r2, r3                      @ compare (vA, vB)
   1557     beq  1f                      @ branch to 1 if comparison failed
   1558     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1559     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1560     bmi     common_backwardBranch       @ yes, do periodic checks
   1561 1:
   1562 #if defined(WITH_JIT)
   1563     GET_JIT_PROF_TABLE(r0)
   1564     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1565     b        common_testUpdateProfile
   1566 #else
   1567     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1568     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1569     GOTO_OPCODE(ip)                     @ jump to next instruction
   1570 #endif
   1571 
   1572 
   1573 /* ------------------------------ */
   1574     .balign 64
   1575 .L_OP_IF_LT: /* 0x34 */
   1576 /* File: armv6t2/OP_IF_LT.S */
   1577 /* File: armv6t2/bincmp.S */
   1578     /*
   1579      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1580      * fragment that specifies the *reverse* comparison to perform, e.g.
   1581      * for "if-le" you would use "gt".
   1582      *
   1583      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1584      */
   1585     /* if-cmp vA, vB, +CCCC */
   1586     mov     r1, rINST, lsr #12          @ r1<- B
   1587     ubfx    r0, rINST, #8, #4           @ r0<- A
   1588     GET_VREG(r3, r1)                    @ r3<- vB
   1589     GET_VREG(r2, r0)                    @ r2<- vA
   1590     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1591     cmp     r2, r3                      @ compare (vA, vB)
   1592     bge  1f                      @ branch to 1 if comparison failed
   1593     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1594     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1595     bmi     common_backwardBranch       @ yes, do periodic checks
   1596 1:
   1597 #if defined(WITH_JIT)
   1598     GET_JIT_PROF_TABLE(r0)
   1599     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1600     b        common_testUpdateProfile
   1601 #else
   1602     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1603     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1604     GOTO_OPCODE(ip)                     @ jump to next instruction
   1605 #endif
   1606 
   1607 
   1608 /* ------------------------------ */
   1609     .balign 64
   1610 .L_OP_IF_GE: /* 0x35 */
   1611 /* File: armv6t2/OP_IF_GE.S */
   1612 /* File: armv6t2/bincmp.S */
   1613     /*
   1614      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1615      * fragment that specifies the *reverse* comparison to perform, e.g.
   1616      * for "if-le" you would use "gt".
   1617      *
   1618      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1619      */
   1620     /* if-cmp vA, vB, +CCCC */
   1621     mov     r1, rINST, lsr #12          @ r1<- B
   1622     ubfx    r0, rINST, #8, #4           @ r0<- A
   1623     GET_VREG(r3, r1)                    @ r3<- vB
   1624     GET_VREG(r2, r0)                    @ r2<- vA
   1625     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1626     cmp     r2, r3                      @ compare (vA, vB)
   1627     blt  1f                      @ branch to 1 if comparison failed
   1628     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1629     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1630     bmi     common_backwardBranch       @ yes, do periodic checks
   1631 1:
   1632 #if defined(WITH_JIT)
   1633     GET_JIT_PROF_TABLE(r0)
   1634     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1635     b        common_testUpdateProfile
   1636 #else
   1637     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1638     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1639     GOTO_OPCODE(ip)                     @ jump to next instruction
   1640 #endif
   1641 
   1642 
   1643 /* ------------------------------ */
   1644     .balign 64
   1645 .L_OP_IF_GT: /* 0x36 */
   1646 /* File: armv6t2/OP_IF_GT.S */
   1647 /* File: armv6t2/bincmp.S */
   1648     /*
   1649      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1650      * fragment that specifies the *reverse* comparison to perform, e.g.
   1651      * for "if-le" you would use "gt".
   1652      *
   1653      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1654      */
   1655     /* if-cmp vA, vB, +CCCC */
   1656     mov     r1, rINST, lsr #12          @ r1<- B
   1657     ubfx    r0, rINST, #8, #4           @ r0<- A
   1658     GET_VREG(r3, r1)                    @ r3<- vB
   1659     GET_VREG(r2, r0)                    @ r2<- vA
   1660     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1661     cmp     r2, r3                      @ compare (vA, vB)
   1662     ble  1f                      @ branch to 1 if comparison failed
   1663     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1664     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1665     bmi     common_backwardBranch       @ yes, do periodic checks
   1666 1:
   1667 #if defined(WITH_JIT)
   1668     GET_JIT_PROF_TABLE(r0)
   1669     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1670     b        common_testUpdateProfile
   1671 #else
   1672     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1673     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1674     GOTO_OPCODE(ip)                     @ jump to next instruction
   1675 #endif
   1676 
   1677 
   1678 /* ------------------------------ */
   1679     .balign 64
   1680 .L_OP_IF_LE: /* 0x37 */
   1681 /* File: armv6t2/OP_IF_LE.S */
   1682 /* File: armv6t2/bincmp.S */
   1683     /*
   1684      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1685      * fragment that specifies the *reverse* comparison to perform, e.g.
   1686      * for "if-le" you would use "gt".
   1687      *
   1688      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1689      */
   1690     /* if-cmp vA, vB, +CCCC */
   1691     mov     r1, rINST, lsr #12          @ r1<- B
   1692     ubfx    r0, rINST, #8, #4           @ r0<- A
   1693     GET_VREG(r3, r1)                    @ r3<- vB
   1694     GET_VREG(r2, r0)                    @ r2<- vA
   1695     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1696     cmp     r2, r3                      @ compare (vA, vB)
   1697     bgt  1f                      @ branch to 1 if comparison failed
   1698     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1699     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1700     bmi     common_backwardBranch       @ yes, do periodic checks
   1701 1:
   1702 #if defined(WITH_JIT)
   1703     GET_JIT_PROF_TABLE(r0)
   1704     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1705     b        common_testUpdateProfile
   1706 #else
   1707     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1708     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1709     GOTO_OPCODE(ip)                     @ jump to next instruction
   1710 #endif
   1711 
   1712 
   1713 /* ------------------------------ */
   1714     .balign 64
   1715 .L_OP_IF_EQZ: /* 0x38 */
   1716 /* File: armv5te/OP_IF_EQZ.S */
   1717 /* File: armv5te/zcmp.S */
   1718     /*
   1719      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1720      * fragment that specifies the *reverse* comparison to perform, e.g.
   1721      * for "if-le" you would use "gt".
   1722      *
   1723      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1724      */
   1725     /* if-cmp vAA, +BBBB */
   1726     mov     r0, rINST, lsr #8           @ r0<- AA
   1727     GET_VREG(r2, r0)                    @ r2<- vAA
   1728     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1729     cmp     r2, #0                      @ compare (vA, 0)
   1730     bne  1f                      @ branch to 1 if comparison failed
   1731     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1732     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1733     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1734 1:
   1735 #if defined(WITH_JIT)
   1736     GET_JIT_PROF_TABLE(r0)
   1737     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1738     cmp     r0,#0
   1739     bne     common_updateProfile
   1740     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1741     GOTO_OPCODE(ip)                     @ jump to next instruction
   1742 #else
   1743     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1744     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1745     GOTO_OPCODE(ip)                     @ jump to next instruction
   1746 #endif
   1747 
   1748 
   1749 /* ------------------------------ */
   1750     .balign 64
   1751 .L_OP_IF_NEZ: /* 0x39 */
   1752 /* File: armv5te/OP_IF_NEZ.S */
   1753 /* File: armv5te/zcmp.S */
   1754     /*
   1755      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1756      * fragment that specifies the *reverse* comparison to perform, e.g.
   1757      * for "if-le" you would use "gt".
   1758      *
   1759      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1760      */
   1761     /* if-cmp vAA, +BBBB */
   1762     mov     r0, rINST, lsr #8           @ r0<- AA
   1763     GET_VREG(r2, r0)                    @ r2<- vAA
   1764     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1765     cmp     r2, #0                      @ compare (vA, 0)
   1766     beq  1f                      @ branch to 1 if comparison failed
   1767     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1768     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1769     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1770 1:
   1771 #if defined(WITH_JIT)
   1772     GET_JIT_PROF_TABLE(r0)
   1773     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1774     cmp     r0,#0
   1775     bne     common_updateProfile
   1776     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1777     GOTO_OPCODE(ip)                     @ jump to next instruction
   1778 #else
   1779     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1780     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1781     GOTO_OPCODE(ip)                     @ jump to next instruction
   1782 #endif
   1783 
   1784 
   1785 /* ------------------------------ */
   1786     .balign 64
   1787 .L_OP_IF_LTZ: /* 0x3a */
   1788 /* File: armv5te/OP_IF_LTZ.S */
   1789 /* File: armv5te/zcmp.S */
   1790     /*
   1791      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1792      * fragment that specifies the *reverse* comparison to perform, e.g.
   1793      * for "if-le" you would use "gt".
   1794      *
   1795      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1796      */
   1797     /* if-cmp vAA, +BBBB */
   1798     mov     r0, rINST, lsr #8           @ r0<- AA
   1799     GET_VREG(r2, r0)                    @ r2<- vAA
   1800     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1801     cmp     r2, #0                      @ compare (vA, 0)
   1802     bge  1f                      @ branch to 1 if comparison failed
   1803     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1804     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1805     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1806 1:
   1807 #if defined(WITH_JIT)
   1808     GET_JIT_PROF_TABLE(r0)
   1809     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1810     cmp     r0,#0
   1811     bne     common_updateProfile
   1812     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1813     GOTO_OPCODE(ip)                     @ jump to next instruction
   1814 #else
   1815     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1816     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1817     GOTO_OPCODE(ip)                     @ jump to next instruction
   1818 #endif
   1819 
   1820 
   1821 /* ------------------------------ */
   1822     .balign 64
   1823 .L_OP_IF_GEZ: /* 0x3b */
   1824 /* File: armv5te/OP_IF_GEZ.S */
   1825 /* File: armv5te/zcmp.S */
   1826     /*
   1827      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1828      * fragment that specifies the *reverse* comparison to perform, e.g.
   1829      * for "if-le" you would use "gt".
   1830      *
   1831      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1832      */
   1833     /* if-cmp vAA, +BBBB */
   1834     mov     r0, rINST, lsr #8           @ r0<- AA
   1835     GET_VREG(r2, r0)                    @ r2<- vAA
   1836     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1837     cmp     r2, #0                      @ compare (vA, 0)
   1838     blt  1f                      @ branch to 1 if comparison failed
   1839     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1840     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1841     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1842 1:
   1843 #if defined(WITH_JIT)
   1844     GET_JIT_PROF_TABLE(r0)
   1845     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1846     cmp     r0,#0
   1847     bne     common_updateProfile
   1848     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1849     GOTO_OPCODE(ip)                     @ jump to next instruction
   1850 #else
   1851     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1852     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1853     GOTO_OPCODE(ip)                     @ jump to next instruction
   1854 #endif
   1855 
   1856 
   1857 /* ------------------------------ */
   1858     .balign 64
   1859 .L_OP_IF_GTZ: /* 0x3c */
   1860 /* File: armv5te/OP_IF_GTZ.S */
   1861 /* File: armv5te/zcmp.S */
   1862     /*
   1863      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1864      * fragment that specifies the *reverse* comparison to perform, e.g.
   1865      * for "if-le" you would use "gt".
   1866      *
   1867      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1868      */
   1869     /* if-cmp vAA, +BBBB */
   1870     mov     r0, rINST, lsr #8           @ r0<- AA
   1871     GET_VREG(r2, r0)                    @ r2<- vAA
   1872     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1873     cmp     r2, #0                      @ compare (vA, 0)
   1874     ble  1f                      @ branch to 1 if comparison failed
   1875     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1876     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1877     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1878 1:
   1879 #if defined(WITH_JIT)
   1880     GET_JIT_PROF_TABLE(r0)
   1881     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1882     cmp     r0,#0
   1883     bne     common_updateProfile
   1884     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1885     GOTO_OPCODE(ip)                     @ jump to next instruction
   1886 #else
   1887     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1888     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1889     GOTO_OPCODE(ip)                     @ jump to next instruction
   1890 #endif
   1891 
   1892 
   1893 /* ------------------------------ */
   1894     .balign 64
   1895 .L_OP_IF_LEZ: /* 0x3d */
   1896 /* File: armv5te/OP_IF_LEZ.S */
   1897 /* File: armv5te/zcmp.S */
   1898     /*
   1899      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1900      * fragment that specifies the *reverse* comparison to perform, e.g.
   1901      * for "if-le" you would use "gt".
   1902      *
   1903      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1904      */
   1905     /* if-cmp vAA, +BBBB */
   1906     mov     r0, rINST, lsr #8           @ r0<- AA
   1907     GET_VREG(r2, r0)                    @ r2<- vAA
   1908     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1909     cmp     r2, #0                      @ compare (vA, 0)
   1910     bgt  1f                      @ branch to 1 if comparison failed
   1911     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1912     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1913     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1914 1:
   1915 #if defined(WITH_JIT)
   1916     GET_JIT_PROF_TABLE(r0)
   1917     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1918     cmp     r0,#0
   1919     bne     common_updateProfile
   1920     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1921     GOTO_OPCODE(ip)                     @ jump to next instruction
   1922 #else
   1923     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1924     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1925     GOTO_OPCODE(ip)                     @ jump to next instruction
   1926 #endif
   1927 
   1928 
   1929 /* ------------------------------ */
   1930     .balign 64
   1931 .L_OP_UNUSED_3E: /* 0x3e */
   1932 /* File: armv5te/OP_UNUSED_3E.S */
   1933 /* File: armv5te/unused.S */
   1934     bl      common_abort
   1935 
   1936 
   1937 /* ------------------------------ */
   1938     .balign 64
   1939 .L_OP_UNUSED_3F: /* 0x3f */
   1940 /* File: armv5te/OP_UNUSED_3F.S */
   1941 /* File: armv5te/unused.S */
   1942     bl      common_abort
   1943 
   1944 
   1945 /* ------------------------------ */
   1946     .balign 64
   1947 .L_OP_UNUSED_40: /* 0x40 */
   1948 /* File: armv5te/OP_UNUSED_40.S */
   1949 /* File: armv5te/unused.S */
   1950     bl      common_abort
   1951 
   1952 
   1953 /* ------------------------------ */
   1954     .balign 64
   1955 .L_OP_UNUSED_41: /* 0x41 */
   1956 /* File: armv5te/OP_UNUSED_41.S */
   1957 /* File: armv5te/unused.S */
   1958     bl      common_abort
   1959 
   1960 
   1961 /* ------------------------------ */
   1962     .balign 64
   1963 .L_OP_UNUSED_42: /* 0x42 */
   1964 /* File: armv5te/OP_UNUSED_42.S */
   1965 /* File: armv5te/unused.S */
   1966     bl      common_abort
   1967 
   1968 
   1969 /* ------------------------------ */
   1970     .balign 64
   1971 .L_OP_UNUSED_43: /* 0x43 */
   1972 /* File: armv5te/OP_UNUSED_43.S */
   1973 /* File: armv5te/unused.S */
   1974     bl      common_abort
   1975 
   1976 
   1977 /* ------------------------------ */
   1978     .balign 64
   1979 .L_OP_AGET: /* 0x44 */
   1980 /* File: armv5te/OP_AGET.S */
   1981     /*
   1982      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   1983      *
   1984      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   1985      * instructions.  We use a pair of FETCH_Bs instead.
   1986      *
   1987      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   1988      */
   1989     /* op vAA, vBB, vCC */
   1990     FETCH_B(r2, 1, 0)                   @ r2<- BB
   1991     mov     r9, rINST, lsr #8           @ r9<- AA
   1992     FETCH_B(r3, 1, 1)                   @ r3<- CC
   1993     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   1994     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   1995     cmp     r0, #0                      @ null array object?
   1996     beq     common_errNullObject        @ yes, bail
   1997     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   1998     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
   1999     cmp     r1, r3                      @ compare unsigned index, length
   2000     bcs     common_errArrayIndex        @ index >= length, bail
   2001     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2002     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2003     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2004     SET_VREG(r2, r9)                    @ vAA<- r2
   2005     GOTO_OPCODE(ip)                     @ jump to next instruction
   2006 
   2007 /* ------------------------------ */
   2008     .balign 64
   2009 .L_OP_AGET_WIDE: /* 0x45 */
   2010 /* File: armv5te/OP_AGET_WIDE.S */
   2011     /*
   2012      * Array get, 64 bits.  vAA <- vBB[vCC].
   2013      *
   2014      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
   2015      */
   2016     /* aget-wide vAA, vBB, vCC */
   2017     FETCH(r0, 1)                        @ r0<- CCBB
   2018     mov     r9, rINST, lsr #8           @ r9<- AA
   2019     and     r2, r0, #255                @ r2<- BB
   2020     mov     r3, r0, lsr #8              @ r3<- CC
   2021     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2022     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2023     cmp     r0, #0                      @ null array object?
   2024     beq     common_errNullObject        @ yes, bail
   2025     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2026     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
   2027     cmp     r1, r3                      @ compare unsigned index, length
   2028     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
   2029     b       common_errArrayIndex        @ index >= length, bail
   2030     @ May want to swap the order of these two branches depending on how the
   2031     @ branch prediction (if any) handles conditional forward branches vs.
   2032     @ unconditional forward branches.
   2033 
   2034 /* ------------------------------ */
   2035     .balign 64
   2036 .L_OP_AGET_OBJECT: /* 0x46 */
   2037 /* File: armv5te/OP_AGET_OBJECT.S */
   2038 /* File: armv5te/OP_AGET.S */
   2039     /*
   2040      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2041      *
   2042      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2043      * instructions.  We use a pair of FETCH_Bs instead.
   2044      *
   2045      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2046      */
   2047     /* op vAA, vBB, vCC */
   2048     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2049     mov     r9, rINST, lsr #8           @ r9<- AA
   2050     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2051     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2052     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2053     cmp     r0, #0                      @ null array object?
   2054     beq     common_errNullObject        @ yes, bail
   2055     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2056     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
   2057     cmp     r1, r3                      @ compare unsigned index, length
   2058     bcs     common_errArrayIndex        @ index >= length, bail
   2059     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2060     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2061     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2062     SET_VREG(r2, r9)                    @ vAA<- r2
   2063     GOTO_OPCODE(ip)                     @ jump to next instruction
   2064 
   2065 
   2066 /* ------------------------------ */
   2067     .balign 64
   2068 .L_OP_AGET_BOOLEAN: /* 0x47 */
   2069 /* File: armv5te/OP_AGET_BOOLEAN.S */
   2070 /* File: armv5te/OP_AGET.S */
   2071     /*
   2072      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2073      *
   2074      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2075      * instructions.  We use a pair of FETCH_Bs instead.
   2076      *
   2077      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2078      */
   2079     /* op vAA, vBB, vCC */
   2080     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2081     mov     r9, rINST, lsr #8           @ r9<- AA
   2082     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2083     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2084     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2085     cmp     r0, #0                      @ null array object?
   2086     beq     common_errNullObject        @ yes, bail
   2087     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2088     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2089     cmp     r1, r3                      @ compare unsigned index, length
   2090     bcs     common_errArrayIndex        @ index >= length, bail
   2091     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2092     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2093     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2094     SET_VREG(r2, r9)                    @ vAA<- r2
   2095     GOTO_OPCODE(ip)                     @ jump to next instruction
   2096 
   2097 
   2098 /* ------------------------------ */
   2099     .balign 64
   2100 .L_OP_AGET_BYTE: /* 0x48 */
   2101 /* File: armv5te/OP_AGET_BYTE.S */
   2102 /* File: armv5te/OP_AGET.S */
   2103     /*
   2104      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2105      *
   2106      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2107      * instructions.  We use a pair of FETCH_Bs instead.
   2108      *
   2109      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2110      */
   2111     /* op vAA, vBB, vCC */
   2112     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2113     mov     r9, rINST, lsr #8           @ r9<- AA
   2114     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2115     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2116     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2117     cmp     r0, #0                      @ null array object?
   2118     beq     common_errNullObject        @ yes, bail
   2119     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2120     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2121     cmp     r1, r3                      @ compare unsigned index, length
   2122     bcs     common_errArrayIndex        @ index >= length, bail
   2123     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2124     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2125     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2126     SET_VREG(r2, r9)                    @ vAA<- r2
   2127     GOTO_OPCODE(ip)                     @ jump to next instruction
   2128 
   2129 
   2130 /* ------------------------------ */
   2131     .balign 64
   2132 .L_OP_AGET_CHAR: /* 0x49 */
   2133 /* File: armv5te/OP_AGET_CHAR.S */
   2134 /* File: armv5te/OP_AGET.S */
   2135     /*
   2136      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2137      *
   2138      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2139      * instructions.  We use a pair of FETCH_Bs instead.
   2140      *
   2141      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2142      */
   2143     /* op vAA, vBB, vCC */
   2144     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2145     mov     r9, rINST, lsr #8           @ r9<- AA
   2146     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2147     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2148     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2149     cmp     r0, #0                      @ null array object?
   2150     beq     common_errNullObject        @ yes, bail
   2151     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2152     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2153     cmp     r1, r3                      @ compare unsigned index, length
   2154     bcs     common_errArrayIndex        @ index >= length, bail
   2155     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2156     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2157     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2158     SET_VREG(r2, r9)                    @ vAA<- r2
   2159     GOTO_OPCODE(ip)                     @ jump to next instruction
   2160 
   2161 
   2162 /* ------------------------------ */
   2163     .balign 64
   2164 .L_OP_AGET_SHORT: /* 0x4a */
   2165 /* File: armv5te/OP_AGET_SHORT.S */
   2166 /* File: armv5te/OP_AGET.S */
   2167     /*
   2168      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2169      *
   2170      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2171      * instructions.  We use a pair of FETCH_Bs instead.
   2172      *
   2173      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2174      */
   2175     /* op vAA, vBB, vCC */
   2176     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2177     mov     r9, rINST, lsr #8           @ r9<- AA
   2178     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2179     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2180     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2181     cmp     r0, #0                      @ null array object?
   2182     beq     common_errNullObject        @ yes, bail
   2183     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2184     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2185     cmp     r1, r3                      @ compare unsigned index, length
   2186     bcs     common_errArrayIndex        @ index >= length, bail
   2187     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2188     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2189     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2190     SET_VREG(r2, r9)                    @ vAA<- r2
   2191     GOTO_OPCODE(ip)                     @ jump to next instruction
   2192 
   2193 
   2194 /* ------------------------------ */
   2195     .balign 64
   2196 .L_OP_APUT: /* 0x4b */
   2197 /* File: armv5te/OP_APUT.S */
   2198     /*
   2199      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2200      *
   2201      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2202      * instructions.  We use a pair of FETCH_Bs instead.
   2203      *
   2204      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2205      */
   2206     /* op vAA, vBB, vCC */
   2207     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2208     mov     r9, rINST, lsr #8           @ r9<- AA
   2209     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2210     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2211     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2212     cmp     r0, #0                      @ null array object?
   2213     beq     common_errNullObject        @ yes, bail
   2214     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2215     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
   2216     cmp     r1, r3                      @ compare unsigned index, length
   2217     bcs     common_errArrayIndex        @ index >= length, bail
   2218     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2219     GET_VREG(r2, r9)                    @ r2<- vAA
   2220     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2221     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2222     GOTO_OPCODE(ip)                     @ jump to next instruction
   2223 
   2224 /* ------------------------------ */
   2225     .balign 64
   2226 .L_OP_APUT_WIDE: /* 0x4c */
   2227 /* File: armv5te/OP_APUT_WIDE.S */
   2228     /*
   2229      * Array put, 64 bits.  vBB[vCC] <- vAA.
   2230      *
   2231      * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
   2232      */
   2233     /* aput-wide vAA, vBB, vCC */
   2234     FETCH(r0, 1)                        @ r0<- CCBB
   2235     mov     r9, rINST, lsr #8           @ r9<- AA
   2236     and     r2, r0, #255                @ r2<- BB
   2237     mov     r3, r0, lsr #8              @ r3<- CC
   2238     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2239     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2240     cmp     r0, #0                      @ null array object?
   2241     beq     common_errNullObject        @ yes, bail
   2242     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2243     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
   2244     cmp     r1, r3                      @ compare unsigned index, length
   2245     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   2246     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
   2247     b       common_errArrayIndex        @ index >= length, bail
   2248     @ May want to swap the order of these two branches depending on how the
   2249     @ branch prediction (if any) handles conditional forward branches vs.
   2250     @ unconditional forward branches.
   2251 
   2252 /* ------------------------------ */
   2253     .balign 64
   2254 .L_OP_APUT_OBJECT: /* 0x4d */
   2255 /* File: armv5te/OP_APUT_OBJECT.S */
   2256     /*
   2257      * Store an object into an array.  vBB[vCC] <- vAA.
   2258      *
   2259      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2260      * instructions.  We use a pair of FETCH_Bs instead.
   2261      */
   2262     /* op vAA, vBB, vCC */
   2263     FETCH(r0, 1)                        @ r0<- CCBB
   2264     mov     r9, rINST, lsr #8           @ r9<- AA
   2265     and     r2, r0, #255                @ r2<- BB
   2266     mov     r3, r0, lsr #8              @ r3<- CC
   2267     GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
   2268     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
   2269     cmp     rINST, #0                   @ null array object?
   2270     GET_VREG(r9, r9)                    @ r9<- vAA
   2271     beq     common_errNullObject        @ yes, bail
   2272     ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
   2273     add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
   2274     cmp     r0, r3                      @ compare unsigned index, length
   2275     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
   2276     b       common_errArrayIndex        @ index >= length, bail
   2277 
   2278 
   2279 /* ------------------------------ */
   2280     .balign 64
   2281 .L_OP_APUT_BOOLEAN: /* 0x4e */
   2282 /* File: armv5te/OP_APUT_BOOLEAN.S */
   2283 /* File: armv5te/OP_APUT.S */
   2284     /*
   2285      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2286      *
   2287      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2288      * instructions.  We use a pair of FETCH_Bs instead.
   2289      *
   2290      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2291      */
   2292     /* op vAA, vBB, vCC */
   2293     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2294     mov     r9, rINST, lsr #8           @ r9<- AA
   2295     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2296     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2297     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2298     cmp     r0, #0                      @ null array object?
   2299     beq     common_errNullObject        @ yes, bail
   2300     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2301     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2302     cmp     r1, r3                      @ compare unsigned index, length
   2303     bcs     common_errArrayIndex        @ index >= length, bail
   2304     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2305     GET_VREG(r2, r9)                    @ r2<- vAA
   2306     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2307     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2308     GOTO_OPCODE(ip)                     @ jump to next instruction
   2309 
   2310 
   2311 /* ------------------------------ */
   2312     .balign 64
   2313 .L_OP_APUT_BYTE: /* 0x4f */
   2314 /* File: armv5te/OP_APUT_BYTE.S */
   2315 /* File: armv5te/OP_APUT.S */
   2316     /*
   2317      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2318      *
   2319      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2320      * instructions.  We use a pair of FETCH_Bs instead.
   2321      *
   2322      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2323      */
   2324     /* op vAA, vBB, vCC */
   2325     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2326     mov     r9, rINST, lsr #8           @ r9<- AA
   2327     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2328     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2329     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2330     cmp     r0, #0                      @ null array object?
   2331     beq     common_errNullObject        @ yes, bail
   2332     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2333     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2334     cmp     r1, r3                      @ compare unsigned index, length
   2335     bcs     common_errArrayIndex        @ index >= length, bail
   2336     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2337     GET_VREG(r2, r9)                    @ r2<- vAA
   2338     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2339     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2340     GOTO_OPCODE(ip)                     @ jump to next instruction
   2341 
   2342 
   2343 /* ------------------------------ */
   2344     .balign 64
   2345 .L_OP_APUT_CHAR: /* 0x50 */
   2346 /* File: armv5te/OP_APUT_CHAR.S */
   2347 /* File: armv5te/OP_APUT.S */
   2348     /*
   2349      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2350      *
   2351      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2352      * instructions.  We use a pair of FETCH_Bs instead.
   2353      *
   2354      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2355      */
   2356     /* op vAA, vBB, vCC */
   2357     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2358     mov     r9, rINST, lsr #8           @ r9<- AA
   2359     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2360     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2361     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2362     cmp     r0, #0                      @ null array object?
   2363     beq     common_errNullObject        @ yes, bail
   2364     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2365     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2366     cmp     r1, r3                      @ compare unsigned index, length
   2367     bcs     common_errArrayIndex        @ index >= length, bail
   2368     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2369     GET_VREG(r2, r9)                    @ r2<- vAA
   2370     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2371     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2372     GOTO_OPCODE(ip)                     @ jump to next instruction
   2373 
   2374 
   2375 /* ------------------------------ */
   2376     .balign 64
   2377 .L_OP_APUT_SHORT: /* 0x51 */
   2378 /* File: armv5te/OP_APUT_SHORT.S */
   2379 /* File: armv5te/OP_APUT.S */
   2380     /*
   2381      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2382      *
   2383      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2384      * instructions.  We use a pair of FETCH_Bs instead.
   2385      *
   2386      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2387      */
   2388     /* op vAA, vBB, vCC */
   2389     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2390     mov     r9, rINST, lsr #8           @ r9<- AA
   2391     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2392     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2393     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2394     cmp     r0, #0                      @ null array object?
   2395     beq     common_errNullObject        @ yes, bail
   2396     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2397     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2398     cmp     r1, r3                      @ compare unsigned index, length
   2399     bcs     common_errArrayIndex        @ index >= length, bail
   2400     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2401     GET_VREG(r2, r9)                    @ r2<- vAA
   2402     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2403     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2404     GOTO_OPCODE(ip)                     @ jump to next instruction
   2405 
   2406 
   2407 /* ------------------------------ */
   2408     .balign 64
   2409 .L_OP_IGET: /* 0x52 */
   2410 /* File: armv6t2/OP_IGET.S */
   2411     /*
   2412      * General 32-bit instance field get.
   2413      *
   2414      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2415      */
   2416     /* op vA, vB, field@CCCC */
   2417     mov     r0, rINST, lsr #12          @ r0<- B
   2418     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2419     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2420     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2421     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2422     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2423     cmp     r0, #0                      @ is resolved entry null?
   2424     bne     .LOP_IGET_finish          @ no, already resolved
   2425 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2426     EXPORT_PC()                         @ resolve() could throw
   2427     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2428     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2429     cmp     r0, #0
   2430     bne     .LOP_IGET_finish
   2431     b       common_exceptionThrown
   2432 
   2433 /* ------------------------------ */
   2434     .balign 64
   2435 .L_OP_IGET_WIDE: /* 0x53 */
   2436 /* File: armv6t2/OP_IGET_WIDE.S */
   2437     /*
   2438      * Wide 32-bit instance field get.
   2439      */
   2440     /* iget-wide vA, vB, field@CCCC */
   2441     mov     r0, rINST, lsr #12          @ r0<- B
   2442     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2443     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2444     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   2445     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2446     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2447     cmp     r0, #0                      @ is resolved entry null?
   2448     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
   2449 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   2450     EXPORT_PC()                         @ resolve() could throw
   2451     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2452     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2453     cmp     r0, #0
   2454     bne     .LOP_IGET_WIDE_finish
   2455     b       common_exceptionThrown
   2456 
   2457 /* ------------------------------ */
   2458     .balign 64
   2459 .L_OP_IGET_OBJECT: /* 0x54 */
   2460 /* File: armv5te/OP_IGET_OBJECT.S */
   2461 /* File: armv5te/OP_IGET.S */
   2462     /*
   2463      * General 32-bit instance field get.
   2464      *
   2465      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2466      */
   2467     /* op vA, vB, field@CCCC */
   2468     mov     r0, rINST, lsr #12          @ r0<- B
   2469     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2470     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2471     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2472     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2473     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2474     cmp     r0, #0                      @ is resolved entry null?
   2475     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
   2476 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2477     EXPORT_PC()                         @ resolve() could throw
   2478     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2479     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2480     cmp     r0, #0
   2481     bne     .LOP_IGET_OBJECT_finish
   2482     b       common_exceptionThrown
   2483 
   2484 
   2485 /* ------------------------------ */
   2486     .balign 64
   2487 .L_OP_IGET_BOOLEAN: /* 0x55 */
   2488 /* File: armv5te/OP_IGET_BOOLEAN.S */
   2489 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
   2490 /* File: armv5te/OP_IGET.S */
   2491     /*
   2492      * General 32-bit instance field get.
   2493      *
   2494      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2495      */
   2496     /* op vA, vB, field@CCCC */
   2497     mov     r0, rINST, lsr #12          @ r0<- B
   2498     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2499     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2500     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2501     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2502     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2503     cmp     r0, #0                      @ is resolved entry null?
   2504     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
   2505 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2506     EXPORT_PC()                         @ resolve() could throw
   2507     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2508     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2509     cmp     r0, #0
   2510     bne     .LOP_IGET_BOOLEAN_finish
   2511     b       common_exceptionThrown
   2512 
   2513 
   2514 /* ------------------------------ */
   2515     .balign 64
   2516 .L_OP_IGET_BYTE: /* 0x56 */
   2517 /* File: armv5te/OP_IGET_BYTE.S */
   2518 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
   2519 /* File: armv5te/OP_IGET.S */
   2520     /*
   2521      * General 32-bit instance field get.
   2522      *
   2523      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2524      */
   2525     /* op vA, vB, field@CCCC */
   2526     mov     r0, rINST, lsr #12          @ r0<- B
   2527     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2528     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2529     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2530     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2531     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2532     cmp     r0, #0                      @ is resolved entry null?
   2533     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
   2534 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2535     EXPORT_PC()                         @ resolve() could throw
   2536     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2537     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2538     cmp     r0, #0
   2539     bne     .LOP_IGET_BYTE_finish
   2540     b       common_exceptionThrown
   2541 
   2542 
   2543 /* ------------------------------ */
   2544     .balign 64
   2545 .L_OP_IGET_CHAR: /* 0x57 */
   2546 /* File: armv5te/OP_IGET_CHAR.S */
   2547 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
   2548 /* File: armv5te/OP_IGET.S */
   2549     /*
   2550      * General 32-bit instance field get.
   2551      *
   2552      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2553      */
   2554     /* op vA, vB, field@CCCC */
   2555     mov     r0, rINST, lsr #12          @ r0<- B
   2556     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2557     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2558     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2559     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2560     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2561     cmp     r0, #0                      @ is resolved entry null?
   2562     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
   2563 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2564     EXPORT_PC()                         @ resolve() could throw
   2565     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2566     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2567     cmp     r0, #0
   2568     bne     .LOP_IGET_CHAR_finish
   2569     b       common_exceptionThrown
   2570 
   2571 
   2572 /* ------------------------------ */
   2573     .balign 64
   2574 .L_OP_IGET_SHORT: /* 0x58 */
   2575 /* File: armv5te/OP_IGET_SHORT.S */
   2576 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
   2577 /* File: armv5te/OP_IGET.S */
   2578     /*
   2579      * General 32-bit instance field get.
   2580      *
   2581      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2582      */
   2583     /* op vA, vB, field@CCCC */
   2584     mov     r0, rINST, lsr #12          @ r0<- B
   2585     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2586     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2587     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2588     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2589     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2590     cmp     r0, #0                      @ is resolved entry null?
   2591     bne     .LOP_IGET_SHORT_finish          @ no, already resolved
   2592 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2593     EXPORT_PC()                         @ resolve() could throw
   2594     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2595     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2596     cmp     r0, #0
   2597     bne     .LOP_IGET_SHORT_finish
   2598     b       common_exceptionThrown
   2599 
   2600 
   2601 /* ------------------------------ */
   2602     .balign 64
   2603 .L_OP_IPUT: /* 0x59 */
   2604 /* File: armv6t2/OP_IPUT.S */
   2605     /*
   2606      * General 32-bit instance field put.
   2607      *
   2608      * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
   2609      */
   2610     /* op vA, vB, field@CCCC */
   2611     mov     r0, rINST, lsr #12          @ r0<- B
   2612     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2613     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2614     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2615     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2616     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2617     cmp     r0, #0                      @ is resolved entry null?
   2618     bne     .LOP_IPUT_finish          @ no, already resolved
   2619 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2620     EXPORT_PC()                         @ resolve() could throw
   2621     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2622     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2623     cmp     r0, #0                      @ success?
   2624     bne     .LOP_IPUT_finish          @ yes, finish up
   2625     b       common_exceptionThrown
   2626 
   2627 /* ------------------------------ */
   2628     .balign 64
   2629 .L_OP_IPUT_WIDE: /* 0x5a */
   2630 /* File: armv6t2/OP_IPUT_WIDE.S */
   2631     /* iput-wide vA, vB, field@CCCC */
   2632     mov     r0, rINST, lsr #12          @ r0<- B
   2633     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2634     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2635     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   2636     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2637     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2638     cmp     r0, #0                      @ is resolved entry null?
   2639     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
   2640 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   2641     EXPORT_PC()                         @ resolve() could throw
   2642     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2643     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2644     cmp     r0, #0                      @ success?
   2645     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
   2646     b       common_exceptionThrown
   2647 
   2648 /* ------------------------------ */
   2649     .balign 64
   2650 .L_OP_IPUT_OBJECT: /* 0x5b */
   2651 /* File: armv5te/OP_IPUT_OBJECT.S */
   2652     /*
   2653      * 32-bit instance field put.
   2654      *
   2655      * for: iput-object, iput-object-volatile
   2656      */
   2657     /* op vA, vB, field@CCCC */
   2658     mov     r0, rINST, lsr #12          @ r0<- B
   2659     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2660     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2661     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2662     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2663     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2664     cmp     r0, #0                      @ is resolved entry null?
   2665     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
   2666 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2667     EXPORT_PC()                         @ resolve() could throw
   2668     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2669     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2670     cmp     r0, #0                      @ success?
   2671     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
   2672     b       common_exceptionThrown
   2673 
   2674 /* ------------------------------ */
   2675     .balign 64
   2676 .L_OP_IPUT_BOOLEAN: /* 0x5c */
   2677 /* File: armv5te/OP_IPUT_BOOLEAN.S */
   2678 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
   2679 /* File: armv5te/OP_IPUT.S */
   2680     /*
   2681      * General 32-bit instance field put.
   2682      *
   2683      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2684      */
   2685     /* op vA, vB, field@CCCC */
   2686     mov     r0, rINST, lsr #12          @ r0<- B
   2687     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2688     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2689     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2690     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2691     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2692     cmp     r0, #0                      @ is resolved entry null?
   2693     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
   2694 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2695     EXPORT_PC()                         @ resolve() could throw
   2696     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2697     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2698     cmp     r0, #0                      @ success?
   2699     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
   2700     b       common_exceptionThrown
   2701 
   2702 
   2703 /* ------------------------------ */
   2704     .balign 64
   2705 .L_OP_IPUT_BYTE: /* 0x5d */
   2706 /* File: armv5te/OP_IPUT_BYTE.S */
   2707 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
   2708 /* File: armv5te/OP_IPUT.S */
   2709     /*
   2710      * General 32-bit instance field put.
   2711      *
   2712      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2713      */
   2714     /* op vA, vB, field@CCCC */
   2715     mov     r0, rINST, lsr #12          @ r0<- B
   2716     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2717     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2718     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2719     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2720     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2721     cmp     r0, #0                      @ is resolved entry null?
   2722     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
   2723 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2724     EXPORT_PC()                         @ resolve() could throw
   2725     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2726     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2727     cmp     r0, #0                      @ success?
   2728     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
   2729     b       common_exceptionThrown
   2730 
   2731 
   2732 /* ------------------------------ */
   2733     .balign 64
   2734 .L_OP_IPUT_CHAR: /* 0x5e */
   2735 /* File: armv5te/OP_IPUT_CHAR.S */
   2736 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
   2737 /* File: armv5te/OP_IPUT.S */
   2738     /*
   2739      * General 32-bit instance field put.
   2740      *
   2741      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2742      */
   2743     /* op vA, vB, field@CCCC */
   2744     mov     r0, rINST, lsr #12          @ r0<- B
   2745     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2746     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2747     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2748     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2749     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2750     cmp     r0, #0                      @ is resolved entry null?
   2751     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
   2752 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2753     EXPORT_PC()                         @ resolve() could throw
   2754     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2755     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2756     cmp     r0, #0                      @ success?
   2757     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
   2758     b       common_exceptionThrown
   2759 
   2760 
   2761 /* ------------------------------ */
   2762     .balign 64
   2763 .L_OP_IPUT_SHORT: /* 0x5f */
   2764 /* File: armv5te/OP_IPUT_SHORT.S */
   2765 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
   2766 /* File: armv5te/OP_IPUT.S */
   2767     /*
   2768      * General 32-bit instance field put.
   2769      *
   2770      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2771      */
   2772     /* op vA, vB, field@CCCC */
   2773     mov     r0, rINST, lsr #12          @ r0<- B
   2774     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2775     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2776     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2777     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2778     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2779     cmp     r0, #0                      @ is resolved entry null?
   2780     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
   2781 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2782     EXPORT_PC()                         @ resolve() could throw
   2783     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2784     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2785     cmp     r0, #0                      @ success?
   2786     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
   2787     b       common_exceptionThrown
   2788 
   2789 
   2790 /* ------------------------------ */
   2791     .balign 64
   2792 .L_OP_SGET: /* 0x60 */
   2793 /* File: armv5te/OP_SGET.S */
   2794     /*
   2795      * General 32-bit SGET handler.
   2796      *
   2797      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2798      */
   2799     /* op vAA, field@BBBB */
   2800     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2801     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2802     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2803     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2804     cmp     r0, #0                      @ is resolved entry null?
   2805     beq     .LOP_SGET_resolve         @ yes, do resolve
   2806 .LOP_SGET_finish: @ field ptr in r0
   2807     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2808     @ no-op                             @ acquiring load
   2809     mov     r2, rINST, lsr #8           @ r2<- AA
   2810     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2811     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2812     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2813     GOTO_OPCODE(ip)                     @ jump to next instruction
   2814 
   2815 /* ------------------------------ */
   2816     .balign 64
   2817 .L_OP_SGET_WIDE: /* 0x61 */
   2818 /* File: armv5te/OP_SGET_WIDE.S */
   2819     /*
   2820      * 64-bit SGET handler.
   2821      */
   2822     /* sget-wide vAA, field@BBBB */
   2823     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2824     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2825     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2826     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2827     cmp     r0, #0                      @ is resolved entry null?
   2828     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
   2829 .LOP_SGET_WIDE_finish:
   2830     mov     r9, rINST, lsr #8           @ r9<- AA
   2831     .if 0
   2832     add     r0, r0, #offStaticField_value @ r0<- pointer to data
   2833     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   2834     .else
   2835     ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
   2836     .endif
   2837     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   2838     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2839     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   2840     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2841     GOTO_OPCODE(ip)                     @ jump to next instruction
   2842 
   2843 /* ------------------------------ */
   2844     .balign 64
   2845 .L_OP_SGET_OBJECT: /* 0x62 */
   2846 /* File: armv5te/OP_SGET_OBJECT.S */
   2847 /* File: armv5te/OP_SGET.S */
   2848     /*
   2849      * General 32-bit SGET handler.
   2850      *
   2851      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2852      */
   2853     /* op vAA, field@BBBB */
   2854     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2855     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2856     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2857     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2858     cmp     r0, #0                      @ is resolved entry null?
   2859     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
   2860 .LOP_SGET_OBJECT_finish: @ field ptr in r0
   2861     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2862     @ no-op                             @ acquiring load
   2863     mov     r2, rINST, lsr #8           @ r2<- AA
   2864     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2865     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2866     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2867     GOTO_OPCODE(ip)                     @ jump to next instruction
   2868 
   2869 
   2870 /* ------------------------------ */
   2871     .balign 64
   2872 .L_OP_SGET_BOOLEAN: /* 0x63 */
   2873 /* File: armv5te/OP_SGET_BOOLEAN.S */
   2874 /* File: armv5te/OP_SGET.S */
   2875     /*
   2876      * General 32-bit SGET handler.
   2877      *
   2878      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2879      */
   2880     /* op vAA, field@BBBB */
   2881     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2882     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2883     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2884     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2885     cmp     r0, #0                      @ is resolved entry null?
   2886     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
   2887 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
   2888     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2889     @ no-op                             @ acquiring load
   2890     mov     r2, rINST, lsr #8           @ r2<- AA
   2891     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2892     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2893     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2894     GOTO_OPCODE(ip)                     @ jump to next instruction
   2895 
   2896 
   2897 /* ------------------------------ */
   2898     .balign 64
   2899 .L_OP_SGET_BYTE: /* 0x64 */
   2900 /* File: armv5te/OP_SGET_BYTE.S */
   2901 /* File: armv5te/OP_SGET.S */
   2902     /*
   2903      * General 32-bit SGET handler.
   2904      *
   2905      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2906      */
   2907     /* op vAA, field@BBBB */
   2908     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2909     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2910     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2911     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2912     cmp     r0, #0                      @ is resolved entry null?
   2913     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
   2914 .LOP_SGET_BYTE_finish: @ field ptr in r0
   2915     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2916     @ no-op                             @ acquiring load
   2917     mov     r2, rINST, lsr #8           @ r2<- AA
   2918     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2919     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2920     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2921     GOTO_OPCODE(ip)                     @ jump to next instruction
   2922 
   2923 
   2924 /* ------------------------------ */
   2925     .balign 64
   2926 .L_OP_SGET_CHAR: /* 0x65 */
   2927 /* File: armv5te/OP_SGET_CHAR.S */
   2928 /* File: armv5te/OP_SGET.S */
   2929     /*
   2930      * General 32-bit SGET handler.
   2931      *
   2932      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2933      */
   2934     /* op vAA, field@BBBB */
   2935     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2936     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2937     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2938     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2939     cmp     r0, #0                      @ is resolved entry null?
   2940     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
   2941 .LOP_SGET_CHAR_finish: @ field ptr in r0
   2942     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2943     @ no-op                             @ acquiring load
   2944     mov     r2, rINST, lsr #8           @ r2<- AA
   2945     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2946     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2947     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2948     GOTO_OPCODE(ip)                     @ jump to next instruction
   2949 
   2950 
   2951 /* ------------------------------ */
   2952     .balign 64
   2953 .L_OP_SGET_SHORT: /* 0x66 */
   2954 /* File: armv5te/OP_SGET_SHORT.S */
   2955 /* File: armv5te/OP_SGET.S */
   2956     /*
   2957      * General 32-bit SGET handler.
   2958      *
   2959      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2960      */
   2961     /* op vAA, field@BBBB */
   2962     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2963     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2964     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2965     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2966     cmp     r0, #0                      @ is resolved entry null?
   2967     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
   2968 .LOP_SGET_SHORT_finish: @ field ptr in r0
   2969     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2970     @ no-op                             @ acquiring load
   2971     mov     r2, rINST, lsr #8           @ r2<- AA
   2972     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2973     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2974     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2975     GOTO_OPCODE(ip)                     @ jump to next instruction
   2976 
   2977 
   2978 /* ------------------------------ */
   2979     .balign 64
   2980 .L_OP_SPUT: /* 0x67 */
   2981 /* File: armv5te/OP_SPUT.S */
   2982     /*
   2983      * General 32-bit SPUT handler.
   2984      *
   2985      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   2986      */
   2987     /* op vAA, field@BBBB */
   2988     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2989     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2990     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2991     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2992     cmp     r0, #0                      @ is resolved entry null?
   2993     beq     .LOP_SPUT_resolve         @ yes, do resolve
   2994 .LOP_SPUT_finish:   @ field ptr in r0
   2995     mov     r2, rINST, lsr #8           @ r2<- AA
   2996     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2997     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   2998     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2999     @ no-op                             @ releasing store
   3000     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3001     GOTO_OPCODE(ip)                     @ jump to next instruction
   3002 
   3003 /* ------------------------------ */
   3004     .balign 64
   3005 .L_OP_SPUT_WIDE: /* 0x68 */
   3006 /* File: armv5te/OP_SPUT_WIDE.S */
   3007     /*
   3008      * 64-bit SPUT handler.
   3009      */
   3010     /* sput-wide vAA, field@BBBB */
   3011     ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
   3012     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3013     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
   3014     mov     r9, rINST, lsr #8           @ r9<- AA
   3015     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
   3016     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   3017     cmp     r2, #0                      @ is resolved entry null?
   3018     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
   3019 .LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
   3020     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3021     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   3022     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   3023     .if 0
   3024     add     r2, r2, #offStaticField_value @ r2<- pointer to data
   3025     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   3026     .else
   3027     strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
   3028     .endif
   3029     GOTO_OPCODE(r10)                    @ jump to next instruction
   3030 
   3031 /* ------------------------------ */
   3032     .balign 64
   3033 .L_OP_SPUT_OBJECT: /* 0x69 */
   3034 /* File: armv5te/OP_SPUT_OBJECT.S */
   3035     /*
   3036      * 32-bit SPUT handler for objects
   3037      *
   3038      * for: sput-object, sput-object-volatile
   3039      */
   3040     /* op vAA, field@BBBB */
   3041     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3042     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3043     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3044     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3045     cmp     r0, #0                      @ is resolved entry null?
   3046     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
   3047     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
   3048     EXPORT_PC()                         @ resolve() could throw, so export now
   3049     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
   3050     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   3051     cmp     r0, #0                      @ success?
   3052     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
   3053     b       common_exceptionThrown      @ no, handle exception
   3054 
   3055 
   3056 /* ------------------------------ */
   3057     .balign 64
   3058 .L_OP_SPUT_BOOLEAN: /* 0x6a */
   3059 /* File: armv5te/OP_SPUT_BOOLEAN.S */
   3060 /* File: armv5te/OP_SPUT.S */
   3061     /*
   3062      * General 32-bit SPUT handler.
   3063      *
   3064      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3065      */
   3066     /* op vAA, field@BBBB */
   3067     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3068     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3069     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3070     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3071     cmp     r0, #0                      @ is resolved entry null?
   3072     beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
   3073 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
   3074     mov     r2, rINST, lsr #8           @ r2<- AA
   3075     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3076     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3077     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3078     @ no-op                             @ releasing store
   3079     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3080     GOTO_OPCODE(ip)                     @ jump to next instruction
   3081 
   3082 
   3083 /* ------------------------------ */
   3084     .balign 64
   3085 .L_OP_SPUT_BYTE: /* 0x6b */
   3086 /* File: armv5te/OP_SPUT_BYTE.S */
   3087 /* File: armv5te/OP_SPUT.S */
   3088     /*
   3089      * General 32-bit SPUT handler.
   3090      *
   3091      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3092      */
   3093     /* op vAA, field@BBBB */
   3094     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3095     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3096     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3097     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3098     cmp     r0, #0                      @ is resolved entry null?
   3099     beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
   3100 .LOP_SPUT_BYTE_finish:   @ field ptr in r0
   3101     mov     r2, rINST, lsr #8           @ r2<- AA
   3102     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3103     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3104     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3105     @ no-op                             @ releasing store
   3106     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3107     GOTO_OPCODE(ip)                     @ jump to next instruction
   3108 
   3109 
   3110 /* ------------------------------ */
   3111     .balign 64
   3112 .L_OP_SPUT_CHAR: /* 0x6c */
   3113 /* File: armv5te/OP_SPUT_CHAR.S */
   3114 /* File: armv5te/OP_SPUT.S */
   3115     /*
   3116      * General 32-bit SPUT handler.
   3117      *
   3118      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3119      */
   3120     /* op vAA, field@BBBB */
   3121     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3122     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3123     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3124     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3125     cmp     r0, #0                      @ is resolved entry null?
   3126     beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
   3127 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
   3128     mov     r2, rINST, lsr #8           @ r2<- AA
   3129     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3130     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3131     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3132     @ no-op                             @ releasing store
   3133     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3134     GOTO_OPCODE(ip)                     @ jump to next instruction
   3135 
   3136 
   3137 /* ------------------------------ */
   3138     .balign 64
   3139 .L_OP_SPUT_SHORT: /* 0x6d */
   3140 /* File: armv5te/OP_SPUT_SHORT.S */
   3141 /* File: armv5te/OP_SPUT.S */
   3142     /*
   3143      * General 32-bit SPUT handler.
   3144      *
   3145      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3146      */
   3147     /* op vAA, field@BBBB */
   3148     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3149     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3150     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3151     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3152     cmp     r0, #0                      @ is resolved entry null?
   3153     beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
   3154 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
   3155     mov     r2, rINST, lsr #8           @ r2<- AA
   3156     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3157     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3158     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3159     @ no-op                             @ releasing store
   3160     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3161     GOTO_OPCODE(ip)                     @ jump to next instruction
   3162 
   3163 
   3164 /* ------------------------------ */
   3165     .balign 64
   3166 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
   3167 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
   3168     /*
   3169      * Handle a virtual method call.
   3170      *
   3171      * for: invoke-virtual, invoke-virtual/range
   3172      */
   3173     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3174     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3175     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3176     FETCH(r1, 1)                        @ r1<- BBBB
   3177     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3178     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3179     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3180     .if     (!0)
   3181     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3182     .endif
   3183     cmp     r0, #0                      @ already resolved?
   3184     EXPORT_PC()                         @ must export for invoke
   3185     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
   3186     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3187     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3188     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   3189     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3190     cmp     r0, #0                      @ got null?
   3191     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
   3192     b       common_exceptionThrown      @ yes, handle exception
   3193 
   3194 /* ------------------------------ */
   3195     .balign 64
   3196 .L_OP_INVOKE_SUPER: /* 0x6f */
   3197 /* File: armv5te/OP_INVOKE_SUPER.S */
   3198     /*
   3199      * Handle a "super" method call.
   3200      *
   3201      * for: invoke-super, invoke-super/range
   3202      */
   3203     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3204     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3205     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3206     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3207     .if     (!0)
   3208     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3209     .endif
   3210     FETCH(r1, 1)                        @ r1<- BBBB
   3211     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3212     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3213     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3214     cmp     r2, #0                      @ null "this"?
   3215     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
   3216     beq     common_errNullObject        @ null "this", throw exception
   3217     cmp     r0, #0                      @ already resolved?
   3218     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
   3219     EXPORT_PC()                         @ must export for invoke
   3220     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
   3221     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
   3222 
   3223 /* ------------------------------ */
   3224     .balign 64
   3225 .L_OP_INVOKE_DIRECT: /* 0x70 */
   3226 /* File: armv5te/OP_INVOKE_DIRECT.S */
   3227     /*
   3228      * Handle a direct method call.
   3229      *
   3230      * (We could defer the "is 'this' pointer null" test to the common
   3231      * method invocation code, and use a flag to indicate that static
   3232      * calls don't count.  If we do this as part of copying the arguments
   3233      * out we could avoiding loading the first arg twice.)
   3234      *
   3235      * for: invoke-direct, invoke-direct/range
   3236      */
   3237     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3238     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3239     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3240     FETCH(r1, 1)                        @ r1<- BBBB
   3241     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3242     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3243     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3244     .if     (!0)
   3245     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3246     .endif
   3247     cmp     r0, #0                      @ already resolved?
   3248     EXPORT_PC()                         @ must export for invoke
   3249     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3250     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
   3251 .LOP_INVOKE_DIRECT_finish:
   3252     cmp     r2, #0                      @ null "this" ref?
   3253     bne     common_invokeMethodNoRange   @ no, continue on
   3254     b       common_errNullObject        @ yes, throw exception
   3255 
   3256 /* ------------------------------ */
   3257     .balign 64
   3258 .L_OP_INVOKE_STATIC: /* 0x71 */
   3259 /* File: armv5te/OP_INVOKE_STATIC.S */
   3260     /*
   3261      * Handle a static method call.
   3262      *
   3263      * for: invoke-static, invoke-static/range
   3264      */
   3265     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3266     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3267     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3268     FETCH(r1, 1)                        @ r1<- BBBB
   3269     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3270     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3271     cmp     r0, #0                      @ already resolved?
   3272     EXPORT_PC()                         @ must export for invoke
   3273     bne     common_invokeMethodNoRange @ yes, continue on
   3274 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3275     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3276     mov     r2, #METHOD_STATIC          @ resolver method type
   3277     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3278     cmp     r0, #0                      @ got null?
   3279     bne     common_invokeMethodNoRange @ no, continue
   3280     b       common_exceptionThrown      @ yes, handle exception
   3281 
   3282 /* ------------------------------ */
   3283     .balign 64
   3284 .L_OP_INVOKE_INTERFACE: /* 0x72 */
   3285 /* File: armv5te/OP_INVOKE_INTERFACE.S */
   3286     /*
   3287      * Handle an interface method call.
   3288      *
   3289      * for: invoke-interface, invoke-interface/range
   3290      */
   3291     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3292     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3293     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
   3294     FETCH(r1, 1)                        @ r1<- BBBB
   3295     .if     (!0)
   3296     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
   3297     .endif
   3298     EXPORT_PC()                         @ must export for invoke
   3299     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
   3300     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
   3301     cmp     r0, #0                      @ null obj?
   3302     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
   3303     beq     common_errNullObject        @ yes, fail
   3304     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
   3305     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
   3306     cmp     r0, #0                      @ failed?
   3307     beq     common_exceptionThrown      @ yes, handle exception
   3308     b       common_invokeMethodNoRange @ jump to common handler
   3309 
   3310 /* ------------------------------ */
   3311     .balign 64
   3312 .L_OP_UNUSED_73: /* 0x73 */
   3313 /* File: armv5te/OP_UNUSED_73.S */
   3314 /* File: armv5te/unused.S */
   3315     bl      common_abort
   3316 
   3317 
   3318 /* ------------------------------ */
   3319     .balign 64
   3320 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
   3321 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
   3322 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
   3323     /*
   3324      * Handle a virtual method call.
   3325      *
   3326      * for: invoke-virtual, invoke-virtual/range
   3327      */
   3328     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3329     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3330     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3331     FETCH(r1, 1)                        @ r1<- BBBB
   3332     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3333     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3334     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3335     .if     (!1)
   3336     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3337     .endif
   3338     cmp     r0, #0                      @ already resolved?
   3339     EXPORT_PC()                         @ must export for invoke
   3340     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
   3341     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3342     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3343     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   3344     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3345     cmp     r0, #0                      @ got null?
   3346     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
   3347     b       common_exceptionThrown      @ yes, handle exception
   3348 
   3349 
   3350 /* ------------------------------ */
   3351     .balign 64
   3352 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
   3353 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
   3354 /* File: armv5te/OP_INVOKE_SUPER.S */
   3355     /*
   3356      * Handle a "super" method call.
   3357      *
   3358      * for: invoke-super, invoke-super/range
   3359      */
   3360     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3361     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3362     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3363     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3364     .if     (!1)
   3365     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3366     .endif
   3367     FETCH(r1, 1)                        @ r1<- BBBB
   3368     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3369     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3370     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3371     cmp     r2, #0                      @ null "this"?
   3372     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
   3373     beq     common_errNullObject        @ null "this", throw exception
   3374     cmp     r0, #0                      @ already resolved?
   3375     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
   3376     EXPORT_PC()                         @ must export for invoke
   3377     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
   3378     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
   3379 
   3380 
   3381 /* ------------------------------ */
   3382     .balign 64
   3383 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
   3384 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
   3385 /* File: armv5te/OP_INVOKE_DIRECT.S */
   3386     /*
   3387      * Handle a direct method call.
   3388      *
   3389      * (We could defer the "is 'this' pointer null" test to the common
   3390      * method invocation code, and use a flag to indicate that static
   3391      * calls don't count.  If we do this as part of copying the arguments
   3392      * out we could avoiding loading the first arg twice.)
   3393      *
   3394      * for: invoke-direct, invoke-direct/range
   3395      */
   3396     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3397     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3398     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3399     FETCH(r1, 1)                        @ r1<- BBBB
   3400     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3401     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3402     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3403     .if     (!1)
   3404     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3405     .endif
   3406     cmp     r0, #0                      @ already resolved?
   3407     EXPORT_PC()                         @ must export for invoke
   3408     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3409     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
   3410 .LOP_INVOKE_DIRECT_RANGE_finish:
   3411     cmp     r2, #0                      @ null "this" ref?
   3412     bne     common_invokeMethodRange   @ no, continue on
   3413     b       common_errNullObject        @ yes, throw exception
   3414 
   3415 
   3416 /* ------------------------------ */
   3417     .balign 64
   3418 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
   3419 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
   3420 /* File: armv5te/OP_INVOKE_STATIC.S */
   3421     /*
   3422      * Handle a static method call.
   3423      *
   3424      * for: invoke-static, invoke-static/range
   3425      */
   3426     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3427     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3428     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3429     FETCH(r1, 1)                        @ r1<- BBBB
   3430     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3431     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3432     cmp     r0, #0                      @ already resolved?
   3433     EXPORT_PC()                         @ must export for invoke
   3434     bne     common_invokeMethodRange @ yes, continue on
   3435 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3436     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3437     mov     r2, #METHOD_STATIC          @ resolver method type
   3438     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3439     cmp     r0, #0                      @ got null?
   3440     bne     common_invokeMethodRange @ no, continue
   3441     b       common_exceptionThrown      @ yes, handle exception
   3442 
   3443 
   3444 /* ------------------------------ */
   3445     .balign 64
   3446 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
   3447 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
   3448 /* File: armv5te/OP_INVOKE_INTERFACE.S */
   3449     /*
   3450      * Handle an interface method call.
   3451      *
   3452      * for: invoke-interface, invoke-interface/range
   3453      */
   3454     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3455     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3456     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
   3457     FETCH(r1, 1)                        @ r1<- BBBB
   3458     .if     (!1)
   3459     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
   3460     .endif
   3461     EXPORT_PC()                         @ must export for invoke
   3462     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
   3463     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
   3464     cmp     r0, #0                      @ null obj?
   3465     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
   3466     beq     common_errNullObject        @ yes, fail
   3467     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
   3468     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
   3469     cmp     r0, #0                      @ failed?
   3470     beq     common_exceptionThrown      @ yes, handle exception
   3471     b       common_invokeMethodRange @ jump to common handler
   3472 
   3473 
   3474 /* ------------------------------ */
   3475     .balign 64
   3476 .L_OP_UNUSED_79: /* 0x79 */
   3477 /* File: armv5te/OP_UNUSED_79.S */
   3478 /* File: armv5te/unused.S */
   3479     bl      common_abort
   3480 
   3481 
   3482 /* ------------------------------ */
   3483     .balign 64
   3484 .L_OP_UNUSED_7A: /* 0x7a */
   3485 /* File: armv5te/OP_UNUSED_7A.S */
   3486 /* File: armv5te/unused.S */
   3487     bl      common_abort
   3488 
   3489 
   3490 /* ------------------------------ */
   3491     .balign 64
   3492 .L_OP_NEG_INT: /* 0x7b */
   3493 /* File: armv6t2/OP_NEG_INT.S */
   3494 /* File: armv6t2/unop.S */
   3495     /*
   3496      * Generic 32-bit unary operation.  Provide an "instr" line that
   3497      * specifies an instruction that performs "result = op r0".
   3498      * This could be an ARM instruction or a function call.
   3499      *
   3500      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3501      *      int-to-byte, int-to-char, int-to-short
   3502      */
   3503     /* unop vA, vB */
   3504     mov     r3, rINST, lsr #12          @ r3<- B
   3505     ubfx    r9, rINST, #8, #4           @ r9<- A
   3506     GET_VREG(r0, r3)                    @ r0<- vB
   3507                                @ optional op; may set condition codes
   3508     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3509     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
   3510     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3511     SET_VREG(r0, r9)                    @ vAA<- r0
   3512     GOTO_OPCODE(ip)                     @ jump to next instruction
   3513     /* 8-9 instructions */
   3514 
   3515 
   3516 /* ------------------------------ */
   3517     .balign 64
   3518 .L_OP_NOT_INT: /* 0x7c */
   3519 /* File: armv6t2/OP_NOT_INT.S */
   3520 /* File: armv6t2/unop.S */
   3521     /*
   3522      * Generic 32-bit unary operation.  Provide an "instr" line that
   3523      * specifies an instruction that performs "result = op r0".
   3524      * This could be an ARM instruction or a function call.
   3525      *
   3526      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3527      *      int-to-byte, int-to-char, int-to-short
   3528      */
   3529     /* unop vA, vB */
   3530     mov     r3, rINST, lsr #12          @ r3<- B
   3531     ubfx    r9, rINST, #8, #4           @ r9<- A
   3532     GET_VREG(r0, r3)                    @ r0<- vB
   3533                                @ optional op; may set condition codes
   3534     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3535     mvn     r0, r0                              @ r0<- op, r0-r3 changed
   3536     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3537     SET_VREG(r0, r9)                    @ vAA<- r0
   3538     GOTO_OPCODE(ip)                     @ jump to next instruction
   3539     /* 8-9 instructions */
   3540 
   3541 
   3542 /* ------------------------------ */
   3543     .balign 64
   3544 .L_OP_NEG_LONG: /* 0x7d */
   3545 /* File: armv6t2/OP_NEG_LONG.S */
   3546 /* File: armv6t2/unopWide.S */
   3547     /*
   3548      * Generic 64-bit unary operation.  Provide an "instr" line that
   3549      * specifies an instruction that performs "result = op r0/r1".
   3550      * This could be an ARM instruction or a function call.
   3551      *
   3552      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3553      */
   3554     /* unop vA, vB */
   3555     mov     r3, rINST, lsr #12          @ r3<- B
   3556     ubfx    r9, rINST, #8, #4           @ r9<- A
   3557     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3558     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3559     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3560     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3561     rsbs    r0, r0, #0                           @ optional op; may set condition codes
   3562     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
   3563     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3564     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3565     GOTO_OPCODE(ip)                     @ jump to next instruction
   3566     /* 10-11 instructions */
   3567 
   3568 
   3569 /* ------------------------------ */
   3570     .balign 64
   3571 .L_OP_NOT_LONG: /* 0x7e */
   3572 /* File: armv6t2/OP_NOT_LONG.S */
   3573 /* File: armv6t2/unopWide.S */
   3574     /*
   3575      * Generic 64-bit unary operation.  Provide an "instr" line that
   3576      * specifies an instruction that performs "result = op r0/r1".
   3577      * This could be an ARM instruction or a function call.
   3578      *
   3579      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3580      */
   3581     /* unop vA, vB */
   3582     mov     r3, rINST, lsr #12          @ r3<- B
   3583     ubfx    r9, rINST, #8, #4           @ r9<- A
   3584     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3585     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3586     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3587     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3588     mvn     r0, r0                           @ optional op; may set condition codes
   3589     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
   3590     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3591     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3592     GOTO_OPCODE(ip)                     @ jump to next instruction
   3593     /* 10-11 instructions */
   3594 
   3595 
   3596 /* ------------------------------ */
   3597     .balign 64
   3598 .L_OP_NEG_FLOAT: /* 0x7f */
   3599 /* File: armv6t2/OP_NEG_FLOAT.S */
   3600 /* File: armv6t2/unop.S */
   3601     /*
   3602      * Generic 32-bit unary operation.  Provide an "instr" line that
   3603      * specifies an instruction that performs "result = op r0".
   3604      * This could be an ARM instruction or a function call.
   3605      *
   3606      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3607      *      int-to-byte, int-to-char, int-to-short
   3608      */
   3609     /* unop vA, vB */
   3610     mov     r3, rINST, lsr #12          @ r3<- B
   3611     ubfx    r9, rINST, #8, #4           @ r9<- A
   3612     GET_VREG(r0, r3)                    @ r0<- vB
   3613                                @ optional op; may set condition codes
   3614     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3615     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
   3616     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3617     SET_VREG(r0, r9)                    @ vAA<- r0
   3618     GOTO_OPCODE(ip)                     @ jump to next instruction
   3619     /* 8-9 instructions */
   3620 
   3621 
   3622 /* ------------------------------ */
   3623     .balign 64
   3624 .L_OP_NEG_DOUBLE: /* 0x80 */
   3625 /* File: armv6t2/OP_NEG_DOUBLE.S */
   3626 /* File: armv6t2/unopWide.S */
   3627     /*
   3628      * Generic 64-bit unary operation.  Provide an "instr" line that
   3629      * specifies an instruction that performs "result = op r0/r1".
   3630      * This could be an ARM instruction or a function call.
   3631      *
   3632      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3633      */
   3634     /* unop vA, vB */
   3635     mov     r3, rINST, lsr #12          @ r3<- B
   3636     ubfx    r9, rINST, #8, #4           @ r9<- A
   3637     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3638     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3639     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3640     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3641                                @ optional op; may set condition codes
   3642     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
   3643     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3644     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3645     GOTO_OPCODE(ip)                     @ jump to next instruction
   3646     /* 10-11 instructions */
   3647 
   3648 
   3649 /* ------------------------------ */
   3650     .balign 64
   3651 .L_OP_INT_TO_LONG: /* 0x81 */
   3652 /* File: armv6t2/OP_INT_TO_LONG.S */
   3653 /* File: armv6t2/unopWider.S */
   3654     /*
   3655      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3656      * that specifies an instruction that performs "result = op r0", where
   3657      * "result" is a 64-bit quantity in r0/r1.
   3658      *
   3659      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3660      */
   3661     /* unop vA, vB */
   3662     mov     r3, rINST, lsr #12          @ r3<- B
   3663     ubfx    r9, rINST, #8, #4           @ r9<- A
   3664     GET_VREG(r0, r3)                    @ r0<- vB
   3665     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3666                                @ optional op; may set condition codes
   3667     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3668     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
   3669     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3670     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3671     GOTO_OPCODE(ip)                     @ jump to next instruction
   3672     /* 9-10 instructions */
   3673 
   3674 
   3675 /* ------------------------------ */
   3676     .balign 64
   3677 .L_OP_INT_TO_FLOAT: /* 0x82 */
   3678 /* File: arm-vfp/OP_INT_TO_FLOAT.S */
   3679 /* File: arm-vfp/funop.S */
   3680     /*
   3681      * Generic 32-bit unary floating-point operation.  Provide an "instr"
   3682      * line that specifies an instruction that performs "s1 = op s0".
   3683      *
   3684      * for: int-to-float, float-to-int
   3685      */
   3686     /* unop vA, vB */
   3687     mov     r3, rINST, lsr #12          @ r3<- B
   3688     mov     r9, rINST, lsr #8           @ r9<- A+
   3689     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3690     flds    s0, [r3]                    @ s0<- vB
   3691     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3692     and     r9, r9, #15                 @ r9<- A
   3693     fsitos  s1, s0                              @ s1<- op
   3694     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3695     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3696     fsts    s1, [r9]                    @ vA<- s1
   3697     GOTO_OPCODE(ip)                     @ jump to next instruction
   3698 
   3699 
   3700 /* ------------------------------ */
   3701     .balign 64
   3702 .L_OP_INT_TO_DOUBLE: /* 0x83 */
   3703 /* File: arm-vfp/OP_INT_TO_DOUBLE.S */
   3704 /* File: arm-vfp/funopWider.S */
   3705     /*
   3706      * Generic 32bit-to-64bit floating point unary operation.  Provide an
   3707      * "instr" line that specifies an instruction that performs "d0 = op s0".
   3708      *
   3709      * For: int-to-double, float-to-double
   3710      */
   3711     /* unop vA, vB */
   3712     mov     r3, rINST, lsr #12          @ r3<- B
   3713     mov     r9, rINST, lsr #8           @ r9<- A+
   3714     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3715     flds    s0, [r3]                    @ s0<- vB
   3716     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3717     and     r9, r9, #15                 @ r9<- A
   3718     fsitod  d0, s0                              @ d0<- op
   3719     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3720     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3721     fstd    d0, [r9]                    @ vA<- d0
   3722     GOTO_OPCODE(ip)                     @ jump to next instruction
   3723 
   3724 
   3725 /* ------------------------------ */
   3726     .balign 64
   3727 .L_OP_LONG_TO_INT: /* 0x84 */
   3728 /* File: armv5te/OP_LONG_TO_INT.S */
   3729 /* we ignore the high word, making this equivalent to a 32-bit reg move */
   3730 /* File: armv5te/OP_MOVE.S */
   3731     /* for move, move-object, long-to-int */
   3732     /* op vA, vB */
   3733     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
   3734     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
   3735     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3736     GET_VREG(r2, r1)                    @ r2<- fp[B]
   3737     and     r0, r0, #15
   3738     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
   3739     SET_VREG(r2, r0)                    @ fp[A]<- r2
   3740     GOTO_OPCODE(ip)                     @ execute next instruction
   3741 
   3742 
   3743 /* ------------------------------ */
   3744     .balign 64
   3745 .L_OP_LONG_TO_FLOAT: /* 0x85 */
   3746 /* File: armv6t2/OP_LONG_TO_FLOAT.S */
   3747 /* File: armv6t2/unopNarrower.S */
   3748     /*
   3749      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
   3750      * that specifies an instruction that performs "result = op r0/r1", where
   3751      * "result" is a 32-bit quantity in r0.
   3752      *
   3753      * For: long-to-float, double-to-int, double-to-float
   3754      *
   3755      * (This would work for long-to-int, but that instruction is actually
   3756      * an exact match for OP_MOVE.)
   3757      */
   3758     /* unop vA, vB */
   3759     mov     r3, rINST, lsr #12          @ r3<- B
   3760     ubfx    r9, rINST, #8, #4           @ r9<- A
   3761     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3762     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
   3763     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3764                                @ optional op; may set condition codes
   3765     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
   3766     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3767     SET_VREG(r0, r9)                    @ vA<- r0
   3768     GOTO_OPCODE(ip)                     @ jump to next instruction
   3769     /* 9-10 instructions */
   3770 
   3771 
   3772 /* ------------------------------ */
   3773     .balign 64
   3774 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
   3775 /* File: armv6t2/OP_LONG_TO_DOUBLE.S */
   3776 /* File: armv6t2/unopWide.S */
   3777     /*
   3778      * Generic 64-bit unary operation.  Provide an "instr" line that
   3779      * specifies an instruction that performs "result = op r0/r1".
   3780      * This could be an ARM instruction or a function call.
   3781      *
   3782      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3783      */
   3784     /* unop vA, vB */
   3785     mov     r3, rINST, lsr #12          @ r3<- B
   3786     ubfx    r9, rINST, #8, #4           @ r9<- A
   3787     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3788     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3789     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3790     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3791                                @ optional op; may set condition codes
   3792     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
   3793     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3794     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3795     GOTO_OPCODE(ip)                     @ jump to next instruction
   3796     /* 10-11 instructions */
   3797 
   3798 
   3799 /* ------------------------------ */
   3800     .balign 64
   3801 .L_OP_FLOAT_TO_INT: /* 0x87 */
   3802 /* File: arm-vfp/OP_FLOAT_TO_INT.S */
   3803 /* File: arm-vfp/funop.S */
   3804     /*
   3805      * Generic 32-bit unary floating-point operation.  Provide an "instr"
   3806      * line that specifies an instruction that performs "s1 = op s0".
   3807      *
   3808      * for: int-to-float, float-to-int
   3809      */
   3810     /* unop vA, vB */
   3811     mov     r3, rINST, lsr #12          @ r3<- B
   3812     mov     r9, rINST, lsr #8           @ r9<- A+
   3813     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3814     flds    s0, [r3]                    @ s0<- vB
   3815     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3816     and     r9, r9, #15                 @ r9<- A
   3817     ftosizs s1, s0                              @ s1<- op
   3818     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3819     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3820     fsts    s1, [r9]                    @ vA<- s1
   3821     GOTO_OPCODE(ip)                     @ jump to next instruction
   3822 
   3823 
   3824 /* ------------------------------ */
   3825     .balign 64
   3826 .L_OP_FLOAT_TO_LONG: /* 0x88 */
   3827 /* File: armv6t2/OP_FLOAT_TO_LONG.S */
   3828 @include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
   3829 /* File: armv6t2/unopWider.S */
   3830     /*
   3831      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3832      * that specifies an instruction that performs "result = op r0", where
   3833      * "result" is a 64-bit quantity in r0/r1.
   3834      *
   3835      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3836      */
   3837     /* unop vA, vB */
   3838     mov     r3, rINST, lsr #12          @ r3<- B
   3839     ubfx    r9, rINST, #8, #4           @ r9<- A
   3840     GET_VREG(r0, r3)                    @ r0<- vB
   3841     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3842                                @ optional op; may set condition codes
   3843     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3844     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
   3845     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3846     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3847     GOTO_OPCODE(ip)                     @ jump to next instruction
   3848     /* 9-10 instructions */
   3849 
   3850 
   3851 
   3852 /* ------------------------------ */
   3853     .balign 64
   3854 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
   3855 /* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
   3856 /* File: arm-vfp/funopWider.S */
   3857     /*
   3858      * Generic 32bit-to-64bit floating point unary operation.  Provide an
   3859      * "instr" line that specifies an instruction that performs "d0 = op s0".
   3860      *
   3861      * For: int-to-double, float-to-double
   3862      */
   3863     /* unop vA, vB */
   3864     mov     r3, rINST, lsr #12          @ r3<- B
   3865     mov     r9, rINST, lsr #8           @ r9<- A+
   3866     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3867     flds    s0, [r3]                    @ s0<- vB
   3868     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3869     and     r9, r9, #15                 @ r9<- A
   3870     fcvtds  d0, s0                              @ d0<- op
   3871     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3872     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3873     fstd    d0, [r9]                    @ vA<- d0
   3874     GOTO_OPCODE(ip)                     @ jump to next instruction
   3875 
   3876 
   3877 /* ------------------------------ */
   3878     .balign 64
   3879 .L_OP_DOUBLE_TO_INT: /* 0x8a */
   3880 /* File: arm-vfp/OP_DOUBLE_TO_INT.S */
   3881 /* File: arm-vfp/funopNarrower.S */
   3882     /*
   3883      * Generic 64bit-to-32bit unary floating point operation.  Provide an
   3884      * "instr" line that specifies an instruction that performs "s0 = op d0".
   3885      *
   3886      * For: double-to-int, double-to-float
   3887      */
   3888     /* unop vA, vB */
   3889     mov     r3, rINST, lsr #12          @ r3<- B
   3890     mov     r9, rINST, lsr #8           @ r9<- A+
   3891     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3892     fldd    d0, [r3]                    @ d0<- vB
   3893     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3894     and     r9, r9, #15                 @ r9<- A
   3895     ftosizd  s0, d0                              @ s0<- op
   3896     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3897     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3898     fsts    s0, [r9]                    @ vA<- s0
   3899     GOTO_OPCODE(ip)                     @ jump to next instruction
   3900 
   3901 
   3902 /* ------------------------------ */
   3903     .balign 64
   3904 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
   3905 /* File: armv6t2/OP_DOUBLE_TO_LONG.S */
   3906 @include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
   3907 /* File: armv6t2/unopWide.S */
   3908     /*
   3909      * Generic 64-bit unary operation.  Provide an "instr" line that
   3910      * specifies an instruction that performs "result = op r0/r1".
   3911      * This could be an ARM instruction or a function call.
   3912      *
   3913      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3914      */
   3915     /* unop vA, vB */
   3916     mov     r3, rINST, lsr #12          @ r3<- B
   3917     ubfx    r9, rINST, #8, #4           @ r9<- A
   3918     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3919     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3920     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3921     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3922                                @ optional op; may set condition codes
   3923     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
   3924     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3925     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3926     GOTO_OPCODE(ip)                     @ jump to next instruction
   3927     /* 10-11 instructions */
   3928 
   3929 
   3930 
   3931 /* ------------------------------ */
   3932     .balign 64
   3933 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
   3934 /* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
   3935 /* File: arm-vfp/funopNarrower.S */
   3936     /*
   3937      * Generic 64bit-to-32bit unary floating point operation.  Provide an
   3938      * "instr" line that specifies an instruction that performs "s0 = op d0".
   3939      *
   3940      * For: double-to-int, double-to-float
   3941      */
   3942     /* unop vA, vB */
   3943     mov     r3, rINST, lsr #12          @ r3<- B
   3944     mov     r9, rINST, lsr #8           @ r9<- A+
   3945     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3946     fldd    d0, [r3]                    @ d0<- vB
   3947     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3948     and     r9, r9, #15                 @ r9<- A
   3949     fcvtsd  s0, d0                              @ s0<- op
   3950     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3951     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3952     fsts    s0, [r9]                    @ vA<- s0
   3953     GOTO_OPCODE(ip)                     @ jump to next instruction
   3954 
   3955 
   3956 /* ------------------------------ */
   3957     .balign 64
   3958 .L_OP_INT_TO_BYTE: /* 0x8d */
   3959 /* File: armv6t2/OP_INT_TO_BYTE.S */
   3960 /* File: armv6t2/unop.S */
   3961     /*
   3962      * Generic 32-bit unary operation.  Provide an "instr" line that
   3963      * specifies an instruction that performs "result = op r0".
   3964      * This could be an ARM instruction or a function call.
   3965      *
   3966      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3967      *      int-to-byte, int-to-char, int-to-short
   3968      */
   3969     /* unop vA, vB */
   3970     mov     r3, rINST, lsr #12          @ r3<- B
   3971     ubfx    r9, rINST, #8, #4           @ r9<- A
   3972     GET_VREG(r0, r3)                    @ r0<- vB
   3973                                @ optional op; may set condition codes
   3974     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3975     sxtb    r0, r0                              @ r0<- op, r0-r3 changed
   3976     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3977     SET_VREG(r0, r9)                    @ vAA<- r0
   3978     GOTO_OPCODE(ip)                     @ jump to next instruction
   3979     /* 8-9 instructions */
   3980 
   3981 
   3982 /* ------------------------------ */
   3983     .balign 64
   3984 .L_OP_INT_TO_CHAR: /* 0x8e */
   3985 /* File: armv6t2/OP_INT_TO_CHAR.S */
   3986 /* File: armv6t2/unop.S */
   3987     /*
   3988      * Generic 32-bit unary operation.  Provide an "instr" line that
   3989      * specifies an instruction that performs "result = op r0".
   3990      * This could be an ARM instruction or a function call.
   3991      *
   3992      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3993      *      int-to-byte, int-to-char, int-to-short
   3994      */
   3995     /* unop vA, vB */
   3996     mov     r3, rINST, lsr #12          @ r3<- B
   3997     ubfx    r9, rINST, #8, #4           @ r9<- A
   3998     GET_VREG(r0, r3)                    @ r0<- vB
   3999                                @ optional op; may set condition codes
   4000     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4001     uxth    r0, r0                              @ r0<- op, r0-r3 changed
   4002     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4003     SET_VREG(r0, r9)                    @ vAA<- r0
   4004     GOTO_OPCODE(ip)                     @ jump to next instruction
   4005     /* 8-9 instructions */
   4006 
   4007 
   4008 /* ------------------------------ */
   4009     .balign 64
   4010 .L_OP_INT_TO_SHORT: /* 0x8f */
   4011 /* File: armv6t2/OP_INT_TO_SHORT.S */
   4012 /* File: armv6t2/unop.S */
   4013     /*
   4014      * Generic 32-bit unary operation.  Provide an "instr" line that
   4015      * specifies an instruction that performs "result = op r0".
   4016      * This could be an ARM instruction or a function call.
   4017      *
   4018      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   4019      *      int-to-byte, int-to-char, int-to-short
   4020      */
   4021     /* unop vA, vB */
   4022     mov     r3, rINST, lsr #12          @ r3<- B
   4023     ubfx    r9, rINST, #8, #4           @ r9<- A
   4024     GET_VREG(r0, r3)                    @ r0<- vB
   4025                                @ optional op; may set condition codes
   4026     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4027     sxth    r0, r0                              @ r0<- op, r0-r3 changed
   4028     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4029     SET_VREG(r0, r9)                    @ vAA<- r0
   4030     GOTO_OPCODE(ip)                     @ jump to next instruction
   4031     /* 8-9 instructions */
   4032 
   4033 
   4034 /* ------------------------------ */
   4035     .balign 64
   4036 .L_OP_ADD_INT: /* 0x90 */
   4037 /* File: armv5te/OP_ADD_INT.S */
   4038 /* File: armv5te/binop.S */
   4039     /*
   4040      * Generic 32-bit binary operation.  Provide an "instr" line that
   4041      * specifies an instruction that performs "result = r0 op r1".
   4042      * This could be an ARM instruction or a function call.  (If the result
   4043      * comes back in a register other than r0, you can override "result".)
   4044      *
   4045      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4046      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4047      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4048      * handles it correctly.
   4049      *
   4050      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4051      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4052      *      mul-float, div-float, rem-float
   4053      */
   4054     /* binop vAA, vBB, vCC */
   4055     FETCH(r0, 1)                        @ r0<- CCBB
   4056     mov     r9, rINST, lsr #8           @ r9<- AA
   4057     mov     r3, r0, lsr #8              @ r3<- CC
   4058     and     r2, r0, #255                @ r2<- BB
   4059     GET_VREG(r1, r3)                    @ r1<- vCC
   4060     GET_VREG(r0, r2)                    @ r0<- vBB
   4061     .if 0
   4062     cmp     r1, #0                      @ is second operand zero?
   4063     beq     common_errDivideByZero
   4064     .endif
   4065 
   4066     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4067                                @ optional op; may set condition codes
   4068     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4069     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4070     SET_VREG(r0, r9)               @ vAA<- r0
   4071     GOTO_OPCODE(ip)                     @ jump to next instruction
   4072     /* 11-14 instructions */
   4073 
   4074 
   4075 /* ------------------------------ */
   4076     .balign 64
   4077 .L_OP_SUB_INT: /* 0x91 */
   4078 /* File: armv5te/OP_SUB_INT.S */
   4079 /* File: armv5te/binop.S */
   4080     /*
   4081      * Generic 32-bit binary operation.  Provide an "instr" line that
   4082      * specifies an instruction that performs "result = r0 op r1".
   4083      * This could be an ARM instruction or a function call.  (If the result
   4084      * comes back in a register other than r0, you can override "result".)
   4085      *
   4086      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4087      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4088      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4089      * handles it correctly.
   4090      *
   4091      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4092      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4093      *      mul-float, div-float, rem-float
   4094      */
   4095     /* binop vAA, vBB, vCC */
   4096     FETCH(r0, 1)                        @ r0<- CCBB
   4097     mov     r9, rINST, lsr #8           @ r9<- AA
   4098     mov     r3, r0, lsr #8              @ r3<- CC
   4099     and     r2, r0, #255                @ r2<- BB
   4100     GET_VREG(r1, r3)                    @ r1<- vCC
   4101     GET_VREG(r0, r2)                    @ r0<- vBB
   4102     .if 0
   4103     cmp     r1, #0                      @ is second operand zero?
   4104     beq     common_errDivideByZero
   4105     .endif
   4106 
   4107     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4108                                @ optional op; may set condition codes
   4109     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4110     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4111     SET_VREG(r0, r9)               @ vAA<- r0
   4112     GOTO_OPCODE(ip)                     @ jump to next instruction
   4113     /* 11-14 instructions */
   4114 
   4115 
   4116 /* ------------------------------ */
   4117     .balign 64
   4118 .L_OP_MUL_INT: /* 0x92 */
   4119 /* File: armv5te/OP_MUL_INT.S */
   4120 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   4121 /* File: armv5te/binop.S */
   4122     /*
   4123      * Generic 32-bit binary operation.  Provide an "instr" line that
   4124      * specifies an instruction that performs "result = r0 op r1".
   4125      * This could be an ARM instruction or a function call.  (If the result
   4126      * comes back in a register other than r0, you can override "result".)
   4127      *
   4128      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4129      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4130      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4131      * handles it correctly.
   4132      *
   4133      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4134      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4135      *      mul-float, div-float, rem-float
   4136      */
   4137     /* binop vAA, vBB, vCC */
   4138     FETCH(r0, 1)                        @ r0<- CCBB
   4139     mov     r9, rINST, lsr #8           @ r9<- AA
   4140     mov     r3, r0, lsr #8              @ r3<- CC
   4141     and     r2, r0, #255                @ r2<- BB
   4142     GET_VREG(r1, r3)                    @ r1<- vCC
   4143     GET_VREG(r0, r2)                    @ r0<- vBB
   4144     .if 0
   4145     cmp     r1, #0                      @ is second operand zero?
   4146     beq     common_errDivideByZero
   4147     .endif
   4148 
   4149     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4150                                @ optional op; may set condition codes
   4151     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   4152     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4153     SET_VREG(r0, r9)               @ vAA<- r0
   4154     GOTO_OPCODE(ip)                     @ jump to next instruction
   4155     /* 11-14 instructions */
   4156 
   4157 
   4158 /* ------------------------------ */
   4159     .balign 64
   4160 .L_OP_DIV_INT: /* 0x93 */
   4161 /* File: armv5te/OP_DIV_INT.S */
   4162 /* File: armv5te/binop.S */
   4163     /*
   4164      * Generic 32-bit binary operation.  Provide an "instr" line that
   4165      * specifies an instruction that performs "result = r0 op r1".
   4166      * This could be an ARM instruction or a function call.  (If the result
   4167      * comes back in a register other than r0, you can override "result".)
   4168      *
   4169      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4170      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4171      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4172      * handles it correctly.
   4173      *
   4174      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4175      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4176      *      mul-float, div-float, rem-float
   4177      */
   4178     /* binop vAA, vBB, vCC */
   4179     FETCH(r0, 1)                        @ r0<- CCBB
   4180     mov     r9, rINST, lsr #8           @ r9<- AA
   4181     mov     r3, r0, lsr #8              @ r3<- CC
   4182     and     r2, r0, #255                @ r2<- BB
   4183     GET_VREG(r1, r3)                    @ r1<- vCC
   4184     GET_VREG(r0, r2)                    @ r0<- vBB
   4185     .if 1
   4186     cmp     r1, #0                      @ is second operand zero?
   4187     beq     common_errDivideByZero
   4188     .endif
   4189 
   4190     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4191                                @ optional op; may set condition codes
   4192     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   4193     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4194     SET_VREG(r0, r9)               @ vAA<- r0
   4195     GOTO_OPCODE(ip)                     @ jump to next instruction
   4196     /* 11-14 instructions */
   4197 
   4198 
   4199 /* ------------------------------ */
   4200     .balign 64
   4201 .L_OP_REM_INT: /* 0x94 */
   4202 /* File: armv5te/OP_REM_INT.S */
   4203 /* idivmod returns quotient in r0 and remainder in r1 */
   4204 /* File: armv5te/binop.S */
   4205     /*
   4206      * Generic 32-bit binary operation.  Provide an "instr" line that
   4207      * specifies an instruction that performs "result = r0 op r1".
   4208      * This could be an ARM instruction or a function call.  (If the result
   4209      * comes back in a register other than r0, you can override "result".)
   4210      *
   4211      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4212      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4213      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4214      * handles it correctly.
   4215      *
   4216      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4217      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4218      *      mul-float, div-float, rem-float
   4219      */
   4220     /* binop vAA, vBB, vCC */
   4221     FETCH(r0, 1)                        @ r0<- CCBB
   4222     mov     r9, rINST, lsr #8           @ r9<- AA
   4223     mov     r3, r0, lsr #8              @ r3<- CC
   4224     and     r2, r0, #255                @ r2<- BB
   4225     GET_VREG(r1, r3)                    @ r1<- vCC
   4226     GET_VREG(r0, r2)                    @ r0<- vBB
   4227     .if 1
   4228     cmp     r1, #0                      @ is second operand zero?
   4229     beq     common_errDivideByZero
   4230     .endif
   4231 
   4232     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4233                                @ optional op; may set condition codes
   4234     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   4235     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4236     SET_VREG(r1, r9)               @ vAA<- r1
   4237     GOTO_OPCODE(ip)                     @ jump to next instruction
   4238     /* 11-14 instructions */
   4239 
   4240 
   4241 /* ------------------------------ */
   4242     .balign 64
   4243 .L_OP_AND_INT: /* 0x95 */
   4244 /* File: armv5te/OP_AND_INT.S */
   4245 /* File: armv5te/binop.S */
   4246     /*
   4247      * Generic 32-bit binary operation.  Provide an "instr" line that
   4248      * specifies an instruction that performs "result = r0 op r1".
   4249      * This could be an ARM instruction or a function call.  (If the result
   4250      * comes back in a register other than r0, you can override "result".)
   4251      *
   4252      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4253      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4254      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4255      * handles it correctly.
   4256      *
   4257      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4258      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4259      *      mul-float, div-float, rem-float
   4260      */
   4261     /* binop vAA, vBB, vCC */
   4262     FETCH(r0, 1)                        @ r0<- CCBB
   4263     mov     r9, rINST, lsr #8           @ r9<- AA
   4264     mov     r3, r0, lsr #8              @ r3<- CC
   4265     and     r2, r0, #255                @ r2<- BB
   4266     GET_VREG(r1, r3)                    @ r1<- vCC
   4267     GET_VREG(r0, r2)                    @ r0<- vBB
   4268     .if 0
   4269     cmp     r1, #0                      @ is second operand zero?
   4270     beq     common_errDivideByZero
   4271     .endif
   4272 
   4273     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4274                                @ optional op; may set condition codes
   4275     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4276     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4277     SET_VREG(r0, r9)               @ vAA<- r0
   4278     GOTO_OPCODE(ip)                     @ jump to next instruction
   4279     /* 11-14 instructions */
   4280 
   4281 
   4282 /* ------------------------------ */
   4283     .balign 64
   4284 .L_OP_OR_INT: /* 0x96 */
   4285 /* File: armv5te/OP_OR_INT.S */
   4286 /* File: armv5te/binop.S */
   4287     /*
   4288      * Generic 32-bit binary operation.  Provide an "instr" line that
   4289      * specifies an instruction that performs "result = r0 op r1".
   4290      * This could be an ARM instruction or a function call.  (If the result
   4291      * comes back in a register other than r0, you can override "result".)
   4292      *
   4293      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4294      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4295      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4296      * handles it correctly.
   4297      *
   4298      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4299      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4300      *      mul-float, div-float, rem-float
   4301      */
   4302     /* binop vAA, vBB, vCC */
   4303     FETCH(r0, 1)                        @ r0<- CCBB
   4304     mov     r9, rINST, lsr #8           @ r9<- AA
   4305     mov     r3, r0, lsr #8              @ r3<- CC
   4306     and     r2, r0, #255                @ r2<- BB
   4307     GET_VREG(r1, r3)                    @ r1<- vCC
   4308     GET_VREG(r0, r2)                    @ r0<- vBB
   4309     .if 0
   4310     cmp     r1, #0                      @ is second operand zero?
   4311     beq     common_errDivideByZero
   4312     .endif
   4313 
   4314     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4315                                @ optional op; may set condition codes
   4316     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4317     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4318     SET_VREG(r0, r9)               @ vAA<- r0
   4319     GOTO_OPCODE(ip)                     @ jump to next instruction
   4320     /* 11-14 instructions */
   4321 
   4322 
   4323 /* ------------------------------ */
   4324     .balign 64
   4325 .L_OP_XOR_INT: /* 0x97 */
   4326 /* File: armv5te/OP_XOR_INT.S */
   4327 /* File: armv5te/binop.S */
   4328     /*
   4329      * Generic 32-bit binary operation.  Provide an "instr" line that
   4330      * specifies an instruction that performs "result = r0 op r1".
   4331      * This could be an ARM instruction or a function call.  (If the result
   4332      * comes back in a register other than r0, you can override "result".)
   4333      *
   4334      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4335      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4336      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4337      * handles it correctly.
   4338      *
   4339      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4340      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4341      *      mul-float, div-float, rem-float
   4342      */
   4343     /* binop vAA, vBB, vCC */
   4344     FETCH(r0, 1)                        @ r0<- CCBB
   4345     mov     r9, rINST, lsr #8           @ r9<- AA
   4346     mov     r3, r0, lsr #8              @ r3<- CC
   4347     and     r2, r0, #255                @ r2<- BB
   4348     GET_VREG(r1, r3)                    @ r1<- vCC
   4349     GET_VREG(r0, r2)                    @ r0<- vBB
   4350     .if 0
   4351     cmp     r1, #0                      @ is second operand zero?
   4352     beq     common_errDivideByZero
   4353     .endif
   4354 
   4355     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4356                                @ optional op; may set condition codes
   4357     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4358     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4359     SET_VREG(r0, r9)               @ vAA<- r0
   4360     GOTO_OPCODE(ip)                     @ jump to next instruction
   4361     /* 11-14 instructions */
   4362 
   4363 
   4364 /* ------------------------------ */
   4365     .balign 64
   4366 .L_OP_SHL_INT: /* 0x98 */
   4367 /* File: armv5te/OP_SHL_INT.S */
   4368 /* File: armv5te/binop.S */
   4369     /*
   4370      * Generic 32-bit binary operation.  Provide an "instr" line that
   4371      * specifies an instruction that performs "result = r0 op r1".
   4372      * This could be an ARM instruction or a function call.  (If the result
   4373      * comes back in a register other than r0, you can override "result".)
   4374      *
   4375      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4376      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4377      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4378      * handles it correctly.
   4379      *
   4380      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4381      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4382      *      mul-float, div-float, rem-float
   4383      */
   4384     /* binop vAA, vBB, vCC */
   4385     FETCH(r0, 1)                        @ r0<- CCBB
   4386     mov     r9, rINST, lsr #8           @ r9<- AA
   4387     mov     r3, r0, lsr #8              @ r3<- CC
   4388     and     r2, r0, #255                @ r2<- BB
   4389     GET_VREG(r1, r3)                    @ r1<- vCC
   4390     GET_VREG(r0, r2)                    @ r0<- vBB
   4391     .if 0
   4392     cmp     r1, #0                      @ is second operand zero?
   4393     beq     common_errDivideByZero
   4394     .endif
   4395 
   4396     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4397     and     r1, r1, #31                           @ optional op; may set condition codes
   4398     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   4399     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4400     SET_VREG(r0, r9)               @ vAA<- r0
   4401     GOTO_OPCODE(ip)                     @ jump to next instruction
   4402     /* 11-14 instructions */
   4403 
   4404 
   4405 /* ------------------------------ */
   4406     .balign 64
   4407 .L_OP_SHR_INT: /* 0x99 */
   4408 /* File: armv5te/OP_SHR_INT.S */
   4409 /* File: armv5te/binop.S */
   4410     /*
   4411      * Generic 32-bit binary operation.  Provide an "instr" line that
   4412      * specifies an instruction that performs "result = r0 op r1".
   4413      * This could be an ARM instruction or a function call.  (If the result
   4414      * comes back in a register other than r0, you can override "result".)
   4415      *
   4416      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4417      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4418      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4419      * handles it correctly.
   4420      *
   4421      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4422      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4423      *      mul-float, div-float, rem-float
   4424      */
   4425     /* binop vAA, vBB, vCC */
   4426     FETCH(r0, 1)                        @ r0<- CCBB
   4427     mov     r9, rINST, lsr #8           @ r9<- AA
   4428     mov     r3, r0, lsr #8              @ r3<- CC
   4429     and     r2, r0, #255                @ r2<- BB
   4430     GET_VREG(r1, r3)                    @ r1<- vCC
   4431     GET_VREG(r0, r2)                    @ r0<- vBB
   4432     .if 0
   4433     cmp     r1, #0                      @ is second operand zero?
   4434     beq     common_errDivideByZero
   4435     .endif
   4436 
   4437     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4438     and     r1, r1, #31                           @ optional op; may set condition codes
   4439     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   4440     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4441     SET_VREG(r0, r9)               @ vAA<- r0
   4442     GOTO_OPCODE(ip)                     @ jump to next instruction
   4443     /* 11-14 instructions */
   4444 
   4445 
   4446 /* ------------------------------ */
   4447     .balign 64
   4448 .L_OP_USHR_INT: /* 0x9a */
   4449 /* File: armv5te/OP_USHR_INT.S */
   4450 /* File: armv5te/binop.S */
   4451     /*
   4452      * Generic 32-bit binary operation.  Provide an "instr" line that
   4453      * specifies an instruction that performs "result = r0 op r1".
   4454      * This could be an ARM instruction or a function call.  (If the result
   4455      * comes back in a register other than r0, you can override "result".)
   4456      *
   4457      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4458      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4459      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4460      * handles it correctly.
   4461      *
   4462      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4463      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4464      *      mul-float, div-float, rem-float
   4465      */
   4466     /* binop vAA, vBB, vCC */
   4467     FETCH(r0, 1)                        @ r0<- CCBB
   4468     mov     r9, rINST, lsr #8           @ r9<- AA
   4469     mov     r3, r0, lsr #8              @ r3<- CC
   4470     and     r2, r0, #255                @ r2<- BB
   4471     GET_VREG(r1, r3)                    @ r1<- vCC
   4472     GET_VREG(r0, r2)                    @ r0<- vBB
   4473     .if 0
   4474     cmp     r1, #0                      @ is second operand zero?
   4475     beq     common_errDivideByZero
   4476     .endif
   4477 
   4478     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4479     and     r1, r1, #31                           @ optional op; may set condition codes
   4480     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   4481     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4482     SET_VREG(r0, r9)               @ vAA<- r0
   4483     GOTO_OPCODE(ip)                     @ jump to next instruction
   4484     /* 11-14 instructions */
   4485 
   4486 
   4487 /* ------------------------------ */
   4488     .balign 64
   4489 .L_OP_ADD_LONG: /* 0x9b */
   4490 /* File: armv5te/OP_ADD_LONG.S */
   4491 /* File: armv5te/binopWide.S */
   4492     /*
   4493      * Generic 64-bit binary operation.  Provide an "instr" line that
   4494      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4495      * This could be an ARM instruction or a function call.  (If the result
   4496      * comes back in a register other than r0, you can override "result".)
   4497      *
   4498      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4499      * vCC (r1).  Useful for integer division and modulus.
   4500      *
   4501      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4502      *      xor-long, add-double, sub-double, mul-double, div-double,
   4503      *      rem-double
   4504      *
   4505      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4506      */
   4507     /* binop vAA, vBB, vCC */
   4508     FETCH(r0, 1)                        @ r0<- CCBB
   4509     mov     r9, rINST, lsr #8           @ r9<- AA
   4510     and     r2, r0, #255                @ r2<- BB
   4511     mov     r3, r0, lsr #8              @ r3<- CC
   4512     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4513     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4514     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4515     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4516     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4517     .if 0
   4518     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4519     beq     common_errDivideByZero
   4520     .endif
   4521     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4522 
   4523     adds    r0, r0, r2                           @ optional op; may set condition codes
   4524     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
   4525     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4526     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4527     GOTO_OPCODE(ip)                     @ jump to next instruction
   4528     /* 14-17 instructions */
   4529 
   4530 
   4531 /* ------------------------------ */
   4532     .balign 64
   4533 .L_OP_SUB_LONG: /* 0x9c */
   4534 /* File: armv5te/OP_SUB_LONG.S */
   4535 /* File: armv5te/binopWide.S */
   4536     /*
   4537      * Generic 64-bit binary operation.  Provide an "instr" line that
   4538      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4539      * This could be an ARM instruction or a function call.  (If the result
   4540      * comes back in a register other than r0, you can override "result".)
   4541      *
   4542      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4543      * vCC (r1).  Useful for integer division and modulus.
   4544      *
   4545      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4546      *      xor-long, add-double, sub-double, mul-double, div-double,
   4547      *      rem-double
   4548      *
   4549      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4550      */
   4551     /* binop vAA, vBB, vCC */
   4552     FETCH(r0, 1)                        @ r0<- CCBB
   4553     mov     r9, rINST, lsr #8           @ r9<- AA
   4554     and     r2, r0, #255                @ r2<- BB
   4555     mov     r3, r0, lsr #8              @ r3<- CC
   4556     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4557     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4558     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4559     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4560     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4561     .if 0
   4562     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4563     beq     common_errDivideByZero
   4564     .endif
   4565     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4566 
   4567     subs    r0, r0, r2                           @ optional op; may set condition codes
   4568     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
   4569     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4570     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4571     GOTO_OPCODE(ip)                     @ jump to next instruction
   4572     /* 14-17 instructions */
   4573 
   4574 
   4575 /* ------------------------------ */
   4576     .balign 64
   4577 .L_OP_MUL_LONG: /* 0x9d */
   4578 /* File: armv5te/OP_MUL_LONG.S */
   4579     /*
   4580      * Signed 64-bit integer multiply.
   4581      *
   4582      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
   4583      *        WX
   4584      *      x YZ
   4585      *  --------
   4586      *     ZW ZX
   4587      *  YW YX
   4588      *
   4589      * The low word of the result holds ZX, the high word holds
   4590      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
   4591      * it doesn't fit in the low 64 bits.
   4592      *
   4593      * Unlike most ARM math operations, multiply instructions have
   4594      * restrictions on using the same register more than once (Rd and Rm
   4595      * cannot be the same).
   4596      */
   4597     /* mul-long vAA, vBB, vCC */
   4598     FETCH(r0, 1)                        @ r0<- CCBB
   4599     and     r2, r0, #255                @ r2<- BB
   4600     mov     r3, r0, lsr #8              @ r3<- CC
   4601     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4602     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4603     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4604     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4605     mul     ip, r2, r1                  @  ip<- ZxW
   4606     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
   4607     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
   4608     mov     r0, rINST, lsr #8           @ r0<- AA
   4609     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
   4610     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
   4611     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4612     b       .LOP_MUL_LONG_finish
   4613 
   4614 /* ------------------------------ */
   4615     .balign 64
   4616 .L_OP_DIV_LONG: /* 0x9e */
   4617 /* File: armv5te/OP_DIV_LONG.S */
   4618 /* File: armv5te/binopWide.S */
   4619     /*
   4620      * Generic 64-bit binary operation.  Provide an "instr" line that
   4621      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4622      * This could be an ARM instruction or a function call.  (If the result
   4623      * comes back in a register other than r0, you can override "result".)
   4624      *
   4625      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4626      * vCC (r1).  Useful for integer division and modulus.
   4627      *
   4628      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4629      *      xor-long, add-double, sub-double, mul-double, div-double,
   4630      *      rem-double
   4631      *
   4632      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4633      */
   4634     /* binop vAA, vBB, vCC */
   4635     FETCH(r0, 1)                        @ r0<- CCBB
   4636     mov     r9, rINST, lsr #8           @ r9<- AA
   4637     and     r2, r0, #255                @ r2<- BB
   4638     mov     r3, r0, lsr #8              @ r3<- CC
   4639     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4640     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4641     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4642     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4643     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4644     .if 1
   4645     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4646     beq     common_errDivideByZero
   4647     .endif
   4648     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4649 
   4650                                @ optional op; may set condition codes
   4651     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   4652     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4653     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4654     GOTO_OPCODE(ip)                     @ jump to next instruction
   4655     /* 14-17 instructions */
   4656 
   4657 
   4658 /* ------------------------------ */
   4659     .balign 64
   4660 .L_OP_REM_LONG: /* 0x9f */
   4661 /* File: armv5te/OP_REM_LONG.S */
   4662 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
   4663 /* File: armv5te/binopWide.S */
   4664     /*
   4665      * Generic 64-bit binary operation.  Provide an "instr" line that
   4666      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4667      * This could be an ARM instruction or a function call.  (If the result
   4668      * comes back in a register other than r0, you can override "result".)
   4669      *
   4670      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4671      * vCC (r1).  Useful for integer division and modulus.
   4672      *
   4673      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4674      *      xor-long, add-double, sub-double, mul-double, div-double,
   4675      *      rem-double
   4676      *
   4677      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4678      */
   4679     /* binop vAA, vBB, vCC */
   4680     FETCH(r0, 1)                        @ r0<- CCBB
   4681     mov     r9, rINST, lsr #8           @ r9<- AA
   4682     and     r2, r0, #255                @ r2<- BB
   4683     mov     r3, r0, lsr #8              @ r3<- CC
   4684     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4685     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4686     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4687     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4688     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4689     .if 1
   4690     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4691     beq     common_errDivideByZero
   4692     .endif
   4693     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4694 
   4695                                @ optional op; may set condition codes
   4696     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   4697     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4698     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
   4699     GOTO_OPCODE(ip)                     @ jump to next instruction
   4700     /* 14-17 instructions */
   4701 
   4702 
   4703 /* ------------------------------ */
   4704     .balign 64
   4705 .L_OP_AND_LONG: /* 0xa0 */
   4706 /* File: armv5te/OP_AND_LONG.S */
   4707 /* File: armv5te/binopWide.S */
   4708     /*
   4709      * Generic 64-bit binary operation.  Provide an "instr" line that
   4710      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4711      * This could be an ARM instruction or a function call.  (If the result
   4712      * comes back in a register other than r0, you can override "result".)
   4713      *
   4714      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4715      * vCC (r1).  Useful for integer division and modulus.
   4716      *
   4717      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4718      *      xor-long, add-double, sub-double, mul-double, div-double,
   4719      *      rem-double
   4720      *
   4721      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4722      */
   4723     /* binop vAA, vBB, vCC */
   4724     FETCH(r0, 1)                        @ r0<- CCBB
   4725     mov     r9, rINST, lsr #8           @ r9<- AA
   4726     and     r2, r0, #255                @ r2<- BB
   4727     mov     r3, r0, lsr #8              @ r3<- CC
   4728     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4729     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4730     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4731     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4732     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4733     .if 0
   4734     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4735     beq     common_errDivideByZero
   4736     .endif
   4737     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4738 
   4739     and     r0, r0, r2                           @ optional op; may set condition codes
   4740     and     r1, r1, r3                              @ result<- op, r0-r3 changed
   4741     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4742     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4743     GOTO_OPCODE(ip)                     @ jump to next instruction
   4744     /* 14-17 instructions */
   4745 
   4746 
   4747 /* ------------------------------ */
   4748     .balign 64
   4749 .L_OP_OR_LONG: /* 0xa1 */
   4750 /* File: armv5te/OP_OR_LONG.S */
   4751 /* File: armv5te/binopWide.S */
   4752     /*
   4753      * Generic 64-bit binary operation.  Provide an "instr" line that
   4754      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4755      * This could be an ARM instruction or a function call.  (If the result
   4756      * comes back in a register other than r0, you can override "result".)
   4757      *
   4758      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4759      * vCC (r1).  Useful for integer division and modulus.
   4760      *
   4761      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4762      *      xor-long, add-double, sub-double, mul-double, div-double,
   4763      *      rem-double
   4764      *
   4765      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4766      */
   4767     /* binop vAA, vBB, vCC */
   4768     FETCH(r0, 1)                        @ r0<- CCBB
   4769     mov     r9, rINST, lsr #8           @ r9<- AA
   4770     and     r2, r0, #255                @ r2<- BB
   4771     mov     r3, r0, lsr #8              @ r3<- CC
   4772     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4773     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4774     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4775     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4776     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4777     .if 0
   4778     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4779     beq     common_errDivideByZero
   4780     .endif
   4781     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4782 
   4783     orr     r0, r0, r2                           @ optional op; may set condition codes
   4784     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
   4785     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4786     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4787     GOTO_OPCODE(ip)                     @ jump to next instruction
   4788     /* 14-17 instructions */
   4789 
   4790 
   4791 /* ------------------------------ */
   4792     .balign 64
   4793 .L_OP_XOR_LONG: /* 0xa2 */
   4794 /* File: armv5te/OP_XOR_LONG.S */
   4795 /* File: armv5te/binopWide.S */
   4796     /*
   4797      * Generic 64-bit binary operation.  Provide an "instr" line that
   4798      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4799      * This could be an ARM instruction or a function call.  (If the result
   4800      * comes back in a register other than r0, you can override "result".)
   4801      *
   4802      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4803      * vCC (r1).  Useful for integer division and modulus.
   4804      *
   4805      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4806      *      xor-long, add-double, sub-double, mul-double, div-double,
   4807      *      rem-double
   4808      *
   4809      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4810      */
   4811     /* binop vAA, vBB, vCC */
   4812     FETCH(r0, 1)                        @ r0<- CCBB
   4813     mov     r9, rINST, lsr #8           @ r9<- AA
   4814     and     r2, r0, #255                @ r2<- BB
   4815     mov     r3, r0, lsr #8              @ r3<- CC
   4816     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4817     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4818     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4819     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4820     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4821     .if 0
   4822     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4823     beq     common_errDivideByZero
   4824     .endif
   4825     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4826 
   4827     eor     r0, r0, r2                           @ optional op; may set condition codes
   4828     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
   4829     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4830     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4831     GOTO_OPCODE(ip)                     @ jump to next instruction
   4832     /* 14-17 instructions */
   4833 
   4834 
   4835 /* ------------------------------ */
   4836     .balign 64
   4837 .L_OP_SHL_LONG: /* 0xa3 */
   4838 /* File: armv5te/OP_SHL_LONG.S */
   4839     /*
   4840      * Long integer shift.  This is different from the generic 32/64-bit
   4841      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4842      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4843      * 6 bits of the shift distance.
   4844      */
   4845     /* shl-long vAA, vBB, vCC */
   4846     FETCH(r0, 1)                        @ r0<- CCBB
   4847     mov     r9, rINST, lsr #8           @ r9<- AA
   4848     and     r3, r0, #255                @ r3<- BB
   4849     mov     r0, r0, lsr #8              @ r0<- CC
   4850     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4851     GET_VREG(r2, r0)                    @ r2<- vCC
   4852     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4853     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   4854     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4855 
   4856     mov     r1, r1, asl r2              @  r1<- r1 << r2
   4857     rsb     r3, r2, #32                 @  r3<- 32 - r2
   4858     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
   4859     subs    ip, r2, #32                 @  ip<- r2 - 32
   4860     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
   4861     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4862     b       .LOP_SHL_LONG_finish
   4863 
   4864 /* ------------------------------ */
   4865     .balign 64
   4866 .L_OP_SHR_LONG: /* 0xa4 */
   4867 /* File: armv5te/OP_SHR_LONG.S */
   4868     /*
   4869      * Long integer shift.  This is different from the generic 32/64-bit
   4870      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4871      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4872      * 6 bits of the shift distance.
   4873      */
   4874     /* shr-long vAA, vBB, vCC */
   4875     FETCH(r0, 1)                        @ r0<- CCBB
   4876     mov     r9, rINST, lsr #8           @ r9<- AA
   4877     and     r3, r0, #255                @ r3<- BB
   4878     mov     r0, r0, lsr #8              @ r0<- CC
   4879     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4880     GET_VREG(r2, r0)                    @ r2<- vCC
   4881     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4882     and     r2, r2, #63                 @ r0<- r0 & 0x3f
   4883     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4884 
   4885     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   4886     rsb     r3, r2, #32                 @  r3<- 32 - r2
   4887     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   4888     subs    ip, r2, #32                 @  ip<- r2 - 32
   4889     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
   4890     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4891     b       .LOP_SHR_LONG_finish
   4892 
   4893 /* ------------------------------ */
   4894     .balign 64
   4895 .L_OP_USHR_LONG: /* 0xa5 */
   4896 /* File: armv5te/OP_USHR_LONG.S */
   4897     /*
   4898      * Long integer shift.  This is different from the generic 32/64-bit
   4899      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4900      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4901      * 6 bits of the shift distance.
   4902      */
   4903     /* ushr-long vAA, vBB, vCC */
   4904     FETCH(r0, 1)                        @ r0<- CCBB
   4905     mov     r9, rINST, lsr #8           @ r9<- AA
   4906     and     r3, r0, #255                @ r3<- BB
   4907     mov     r0, r0, lsr #8              @ r0<- CC
   4908     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4909     GET_VREG(r2, r0)                    @ r2<- vCC
   4910     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4911     and     r2, r2, #63                 @ r0<- r0 & 0x3f
   4912     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4913 
   4914     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   4915     rsb     r3, r2, #32                 @  r3<- 32 - r2
   4916     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   4917     subs    ip, r2, #32                 @  ip<- r2 - 32
   4918     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
   4919     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4920     b       .LOP_USHR_LONG_finish
   4921 
   4922 /* ------------------------------ */
   4923     .balign 64
   4924 .L_OP_ADD_FLOAT: /* 0xa6 */
   4925 /* File: arm-vfp/OP_ADD_FLOAT.S */
   4926 /* File: arm-vfp/fbinop.S */
   4927     /*
   4928      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   4929      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   4930      * use the "softfp" ABI, this must be an instruction, not a function call.
   4931      *
   4932      * For: add-float, sub-float, mul-float, div-float
   4933      */
   4934     /* floatop vAA, vBB, vCC */
   4935     FETCH(r0, 1)                        @ r0<- CCBB
   4936     mov     r9, rINST, lsr #8           @ r9<- AA
   4937     mov     r3, r0, lsr #8              @ r3<- CC
   4938     and     r2, r0, #255                @ r2<- BB
   4939     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   4940     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   4941     flds    s1, [r3]                    @ s1<- vCC
   4942     flds    s0, [r2]                    @ s0<- vBB
   4943 
   4944     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4945     fadds   s2, s0, s1                              @ s2<- op
   4946     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4947     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   4948     fsts    s2, [r9]                    @ vAA<- s2
   4949     GOTO_OPCODE(ip)                     @ jump to next instruction
   4950 
   4951 
   4952 /* ------------------------------ */
   4953     .balign 64
   4954 .L_OP_SUB_FLOAT: /* 0xa7 */
   4955 /* File: arm-vfp/OP_SUB_FLOAT.S */
   4956 /* File: arm-vfp/fbinop.S */
   4957     /*
   4958      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   4959      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   4960      * use the "softfp" ABI, this must be an instruction, not a function call.
   4961      *
   4962      * For: add-float, sub-float, mul-float, div-float
   4963      */
   4964     /* floatop vAA, vBB, vCC */
   4965     FETCH(r0, 1)                        @ r0<- CCBB
   4966     mov     r9, rINST, lsr #8           @ r9<- AA
   4967     mov     r3, r0, lsr #8              @ r3<- CC
   4968     and     r2, r0, #255                @ r2<- BB
   4969     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   4970     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   4971     flds    s1, [r3]                    @ s1<- vCC
   4972     flds    s0, [r2]                    @ s0<- vBB
   4973 
   4974     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4975     fsubs   s2, s0, s1                              @ s2<- op
   4976     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4977     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   4978     fsts    s2, [r9]                    @ vAA<- s2
   4979     GOTO_OPCODE(ip)                     @ jump to next instruction
   4980 
   4981 
   4982 /* ------------------------------ */
   4983     .balign 64
   4984 .L_OP_MUL_FLOAT: /* 0xa8 */
   4985 /* File: arm-vfp/OP_MUL_FLOAT.S */
   4986 /* File: arm-vfp/fbinop.S */
   4987     /*
   4988      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   4989      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   4990      * use the "softfp" ABI, this must be an instruction, not a function call.
   4991      *
   4992      * For: add-float, sub-float, mul-float, div-float
   4993      */
   4994     /* floatop vAA, vBB, vCC */
   4995     FETCH(r0, 1)                        @ r0<- CCBB
   4996     mov     r9, rINST, lsr #8           @ r9<- AA
   4997     mov     r3, r0, lsr #8              @ r3<- CC
   4998     and     r2, r0, #255                @ r2<- BB
   4999     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5000     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5001     flds    s1, [r3]                    @ s1<- vCC
   5002     flds    s0, [r2]                    @ s0<- vBB
   5003 
   5004     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5005     fmuls   s2, s0, s1                              @ s2<- op
   5006     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5007     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5008     fsts    s2, [r9]                    @ vAA<- s2
   5009     GOTO_OPCODE(ip)                     @ jump to next instruction
   5010 
   5011 
   5012 /* ------------------------------ */
   5013     .balign 64
   5014 .L_OP_DIV_FLOAT: /* 0xa9 */
   5015 /* File: arm-vfp/OP_DIV_FLOAT.S */
   5016 /* File: arm-vfp/fbinop.S */
   5017     /*
   5018      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   5019      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   5020      * use the "softfp" ABI, this must be an instruction, not a function call.
   5021      *
   5022      * For: add-float, sub-float, mul-float, div-float
   5023      */
   5024     /* floatop vAA, vBB, vCC */
   5025     FETCH(r0, 1)                        @ r0<- CCBB
   5026     mov     r9, rINST, lsr #8           @ r9<- AA
   5027     mov     r3, r0, lsr #8              @ r3<- CC
   5028     and     r2, r0, #255                @ r2<- BB
   5029     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5030     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5031     flds    s1, [r3]                    @ s1<- vCC
   5032     flds    s0, [r2]                    @ s0<- vBB
   5033 
   5034     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5035     fdivs   s2, s0, s1                              @ s2<- op
   5036     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5037     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5038     fsts    s2, [r9]                    @ vAA<- s2
   5039     GOTO_OPCODE(ip)                     @ jump to next instruction
   5040 
   5041 
   5042 /* ------------------------------ */
   5043     .balign 64
   5044 .L_OP_REM_FLOAT: /* 0xaa */
   5045 /* File: armv5te/OP_REM_FLOAT.S */
   5046 /* EABI doesn't define a float remainder function, but libm does */
   5047 /* File: armv5te/binop.S */
   5048     /*
   5049      * Generic 32-bit binary operation.  Provide an "instr" line that
   5050      * specifies an instruction that performs "result = r0 op r1".
   5051      * This could be an ARM instruction or a function call.  (If the result
   5052      * comes back in a register other than r0, you can override "result".)
   5053      *
   5054      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5055      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5056      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5057      * handles it correctly.
   5058      *
   5059      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5060      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5061      *      mul-float, div-float, rem-float
   5062      */
   5063     /* binop vAA, vBB, vCC */
   5064     FETCH(r0, 1)                        @ r0<- CCBB
   5065     mov     r9, rINST, lsr #8           @ r9<- AA
   5066     mov     r3, r0, lsr #8              @ r3<- CC
   5067     and     r2, r0, #255                @ r2<- BB
   5068     GET_VREG(r1, r3)                    @ r1<- vCC
   5069     GET_VREG(r0, r2)                    @ r0<- vBB
   5070     .if 0
   5071     cmp     r1, #0                      @ is second operand zero?
   5072     beq     common_errDivideByZero
   5073     .endif
   5074 
   5075     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5076                                @ optional op; may set condition codes
   5077     bl      fmodf                              @ r0<- op, r0-r3 changed
   5078     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5079     SET_VREG(r0, r9)               @ vAA<- r0
   5080     GOTO_OPCODE(ip)                     @ jump to next instruction
   5081     /* 11-14 instructions */
   5082 
   5083 
   5084 /* ------------------------------ */
   5085     .balign 64
   5086 .L_OP_ADD_DOUBLE: /* 0xab */
   5087 /* File: arm-vfp/OP_ADD_DOUBLE.S */
   5088 /* File: arm-vfp/fbinopWide.S */
   5089     /*
   5090      * Generic 64-bit double-precision floating point binary operation.
   5091      * Provide an "instr" line that specifies an instruction that performs
   5092      * "d2 = d0 op d1".
   5093      *
   5094      * for: add-double, sub-double, mul-double, div-double
   5095      */
   5096     /* doubleop vAA, vBB, vCC */
   5097     FETCH(r0, 1)                        @ r0<- CCBB
   5098     mov     r9, rINST, lsr #8           @ r9<- AA
   5099     mov     r3, r0, lsr #8              @ r3<- CC
   5100     and     r2, r0, #255                @ r2<- BB
   5101     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5102     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5103     fldd    d1, [r3]                    @ d1<- vCC
   5104     fldd    d0, [r2]                    @ d0<- vBB
   5105 
   5106     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5107     faddd   d2, d0, d1                              @ s2<- op
   5108     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5109     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5110     fstd    d2, [r9]                    @ vAA<- d2
   5111     GOTO_OPCODE(ip)                     @ jump to next instruction
   5112 
   5113 
   5114 /* ------------------------------ */
   5115     .balign 64
   5116 .L_OP_SUB_DOUBLE: /* 0xac */
   5117 /* File: arm-vfp/OP_SUB_DOUBLE.S */
   5118 /* File: arm-vfp/fbinopWide.S */
   5119     /*
   5120      * Generic 64-bit double-precision floating point binary operation.
   5121      * Provide an "instr" line that specifies an instruction that performs
   5122      * "d2 = d0 op d1".
   5123      *
   5124      * for: add-double, sub-double, mul-double, div-double
   5125      */
   5126     /* doubleop vAA, vBB, vCC */
   5127     FETCH(r0, 1)                        @ r0<- CCBB
   5128     mov     r9, rINST, lsr #8           @ r9<- AA
   5129     mov     r3, r0, lsr #8              @ r3<- CC
   5130     and     r2, r0, #255                @ r2<- BB
   5131     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5132     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5133     fldd    d1, [r3]                    @ d1<- vCC
   5134     fldd    d0, [r2]                    @ d0<- vBB
   5135 
   5136     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5137     fsubd   d2, d0, d1                              @ s2<- op
   5138     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5139     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5140     fstd    d2, [r9]                    @ vAA<- d2
   5141     GOTO_OPCODE(ip)                     @ jump to next instruction
   5142 
   5143 
   5144 /* ------------------------------ */
   5145     .balign 64
   5146 .L_OP_MUL_DOUBLE: /* 0xad */
   5147 /* File: arm-vfp/OP_MUL_DOUBLE.S */
   5148 /* File: arm-vfp/fbinopWide.S */
   5149     /*
   5150      * Generic 64-bit double-precision floating point binary operation.
   5151      * Provide an "instr" line that specifies an instruction that performs
   5152      * "d2 = d0 op d1".
   5153      *
   5154      * for: add-double, sub-double, mul-double, div-double
   5155      */
   5156     /* doubleop vAA, vBB, vCC */
   5157     FETCH(r0, 1)                        @ r0<- CCBB
   5158     mov     r9, rINST, lsr #8           @ r9<- AA
   5159     mov     r3, r0, lsr #8              @ r3<- CC
   5160     and     r2, r0, #255                @ r2<- BB
   5161     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5162     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5163     fldd    d1, [r3]                    @ d1<- vCC
   5164     fldd    d0, [r2]                    @ d0<- vBB
   5165 
   5166     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5167     fmuld   d2, d0, d1                              @ s2<- op
   5168     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5169     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5170     fstd    d2, [r9]                    @ vAA<- d2
   5171     GOTO_OPCODE(ip)                     @ jump to next instruction
   5172 
   5173 
   5174 /* ------------------------------ */
   5175     .balign 64
   5176 .L_OP_DIV_DOUBLE: /* 0xae */
   5177 /* File: arm-vfp/OP_DIV_DOUBLE.S */
   5178 /* File: arm-vfp/fbinopWide.S */
   5179     /*
   5180      * Generic 64-bit double-precision floating point binary operation.
   5181      * Provide an "instr" line that specifies an instruction that performs
   5182      * "d2 = d0 op d1".
   5183      *
   5184      * for: add-double, sub-double, mul-double, div-double
   5185      */
   5186     /* doubleop vAA, vBB, vCC */
   5187     FETCH(r0, 1)                        @ r0<- CCBB
   5188     mov     r9, rINST, lsr #8           @ r9<- AA
   5189     mov     r3, r0, lsr #8              @ r3<- CC
   5190     and     r2, r0, #255                @ r2<- BB
   5191     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5192     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5193     fldd    d1, [r3]                    @ d1<- vCC
   5194     fldd    d0, [r2]                    @ d0<- vBB
   5195 
   5196     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5197     fdivd   d2, d0, d1                              @ s2<- op
   5198     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5199     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5200     fstd    d2, [r9]                    @ vAA<- d2
   5201     GOTO_OPCODE(ip)                     @ jump to next instruction
   5202 
   5203 
   5204 /* ------------------------------ */
   5205     .balign 64
   5206 .L_OP_REM_DOUBLE: /* 0xaf */
   5207 /* File: armv5te/OP_REM_DOUBLE.S */
   5208 /* EABI doesn't define a double remainder function, but libm does */
   5209 /* File: armv5te/binopWide.S */
   5210     /*
   5211      * Generic 64-bit binary operation.  Provide an "instr" line that
   5212      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5213      * This could be an ARM instruction or a function call.  (If the result
   5214      * comes back in a register other than r0, you can override "result".)
   5215      *
   5216      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5217      * vCC (r1).  Useful for integer division and modulus.
   5218      *
   5219      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5220      *      xor-long, add-double, sub-double, mul-double, div-double,
   5221      *      rem-double
   5222      *
   5223      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5224      */
   5225     /* binop vAA, vBB, vCC */
   5226     FETCH(r0, 1)                        @ r0<- CCBB
   5227     mov     r9, rINST, lsr #8           @ r9<- AA
   5228     and     r2, r0, #255                @ r2<- BB
   5229     mov     r3, r0, lsr #8              @ r3<- CC
   5230     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5231     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5232     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5233     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5234     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5235     .if 0
   5236     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5237     beq     common_errDivideByZero
   5238     .endif
   5239     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5240 
   5241                                @ optional op; may set condition codes
   5242     bl      fmod                              @ result<- op, r0-r3 changed
   5243     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5244     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5245     GOTO_OPCODE(ip)                     @ jump to next instruction
   5246     /* 14-17 instructions */
   5247 
   5248 
   5249 /* ------------------------------ */
   5250     .balign 64
   5251 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
   5252 /* File: armv6t2/OP_ADD_INT_2ADDR.S */
   5253 /* File: armv6t2/binop2addr.S */
   5254     /*
   5255      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5256      * that specifies an instruction that performs "result = r0 op r1".
   5257      * This could be an ARM instruction or a function call.  (If the result
   5258      * comes back in a register other than r0, you can override "result".)
   5259      *
   5260      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5261      * vCC (r1).  Useful for integer division and modulus.
   5262      *
   5263      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5264      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5265      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5266      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5267      */
   5268     /* binop/2addr vA, vB */
   5269     mov     r3, rINST, lsr #12          @ r3<- B
   5270     ubfx    r9, rINST, #8, #4           @ r9<- A
   5271     GET_VREG(r1, r3)                    @ r1<- vB
   5272     GET_VREG(r0, r9)                    @ r0<- vA
   5273     .if 0
   5274     cmp     r1, #0                      @ is second operand zero?
   5275     beq     common_errDivideByZero
   5276     .endif
   5277     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5278 
   5279                                @ optional op; may set condition codes
   5280     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5281     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5282     SET_VREG(r0, r9)               @ vAA<- r0
   5283     GOTO_OPCODE(ip)                     @ jump to next instruction
   5284     /* 10-13 instructions */
   5285 
   5286 
   5287 /* ------------------------------ */
   5288     .balign 64
   5289 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
   5290 /* File: armv6t2/OP_SUB_INT_2ADDR.S */
   5291 /* File: armv6t2/binop2addr.S */
   5292     /*
   5293      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5294      * that specifies an instruction that performs "result = r0 op r1".
   5295      * This could be an ARM instruction or a function call.  (If the result
   5296      * comes back in a register other than r0, you can override "result".)
   5297      *
   5298      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5299      * vCC (r1).  Useful for integer division and modulus.
   5300      *
   5301      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5302      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5303      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5304      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5305      */
   5306     /* binop/2addr vA, vB */
   5307     mov     r3, rINST, lsr #12          @ r3<- B
   5308     ubfx    r9, rINST, #8, #4           @ r9<- A
   5309     GET_VREG(r1, r3)                    @ r1<- vB
   5310     GET_VREG(r0, r9)                    @ r0<- vA
   5311     .if 0
   5312     cmp     r1, #0                      @ is second operand zero?
   5313     beq     common_errDivideByZero
   5314     .endif
   5315     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5316 
   5317                                @ optional op; may set condition codes
   5318     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5319     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5320     SET_VREG(r0, r9)               @ vAA<- r0
   5321     GOTO_OPCODE(ip)                     @ jump to next instruction
   5322     /* 10-13 instructions */
   5323 
   5324 
   5325 /* ------------------------------ */
   5326     .balign 64
   5327 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
   5328 /* File: armv6t2/OP_MUL_INT_2ADDR.S */
   5329 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   5330 /* File: armv6t2/binop2addr.S */
   5331     /*
   5332      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5333      * that specifies an instruction that performs "result = r0 op r1".
   5334      * This could be an ARM instruction or a function call.  (If the result
   5335      * comes back in a register other than r0, you can override "result".)
   5336      *
   5337      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5338      * vCC (r1).  Useful for integer division and modulus.
   5339      *
   5340      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5341      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5342      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5343      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5344      */
   5345     /* binop/2addr vA, vB */
   5346     mov     r3, rINST, lsr #12          @ r3<- B
   5347     ubfx    r9, rINST, #8, #4           @ r9<- A
   5348     GET_VREG(r1, r3)                    @ r1<- vB
   5349     GET_VREG(r0, r9)                    @ r0<- vA
   5350     .if 0
   5351     cmp     r1, #0                      @ is second operand zero?
   5352     beq     common_errDivideByZero
   5353     .endif
   5354     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5355 
   5356                                @ optional op; may set condition codes
   5357     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   5358     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5359     SET_VREG(r0, r9)               @ vAA<- r0
   5360     GOTO_OPCODE(ip)                     @ jump to next instruction
   5361     /* 10-13 instructions */
   5362 
   5363 
   5364 /* ------------------------------ */
   5365     .balign 64
   5366 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
   5367 /* File: armv6t2/OP_DIV_INT_2ADDR.S */
   5368 /* File: armv6t2/binop2addr.S */
   5369     /*
   5370      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5371      * that specifies an instruction that performs "result = r0 op r1".
   5372      * This could be an ARM instruction or a function call.  (If the result
   5373      * comes back in a register other than r0, you can override "result".)
   5374      *
   5375      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5376      * vCC (r1).  Useful for integer division and modulus.
   5377      *
   5378      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5379      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5380      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5381      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5382      */
   5383     /* binop/2addr vA, vB */
   5384     mov     r3, rINST, lsr #12          @ r3<- B
   5385     ubfx    r9, rINST, #8, #4           @ r9<- A
   5386     GET_VREG(r1, r3)                    @ r1<- vB
   5387     GET_VREG(r0, r9)                    @ r0<- vA
   5388     .if 1
   5389     cmp     r1, #0                      @ is second operand zero?
   5390     beq     common_errDivideByZero
   5391     .endif
   5392     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5393 
   5394                                @ optional op; may set condition codes
   5395     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   5396     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5397     SET_VREG(r0, r9)               @ vAA<- r0
   5398     GOTO_OPCODE(ip)                     @ jump to next instruction
   5399     /* 10-13 instructions */
   5400 
   5401 
   5402 /* ------------------------------ */
   5403     .balign 64
   5404 .L_OP_REM_INT_2ADDR: /* 0xb4 */
   5405 /* File: armv6t2/OP_REM_INT_2ADDR.S */
   5406 /* idivmod returns quotient in r0 and remainder in r1 */
   5407 /* File: armv6t2/binop2addr.S */
   5408     /*
   5409      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5410      * that specifies an instruction that performs "result = r0 op r1".
   5411      * This could be an ARM instruction or a function call.  (If the result
   5412      * comes back in a register other than r0, you can override "result".)
   5413      *
   5414      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5415      * vCC (r1).  Useful for integer division and modulus.
   5416      *
   5417      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5418      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5419      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5420      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5421      */
   5422     /* binop/2addr vA, vB */
   5423     mov     r3, rINST, lsr #12          @ r3<- B
   5424     ubfx    r9, rINST, #8, #4           @ r9<- A
   5425     GET_VREG(r1, r3)                    @ r1<- vB
   5426     GET_VREG(r0, r9)                    @ r0<- vA
   5427     .if 1
   5428     cmp     r1, #0                      @ is second operand zero?
   5429     beq     common_errDivideByZero
   5430     .endif
   5431     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5432 
   5433                                @ optional op; may set condition codes
   5434     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   5435     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5436     SET_VREG(r1, r9)               @ vAA<- r1
   5437     GOTO_OPCODE(ip)                     @ jump to next instruction
   5438     /* 10-13 instructions */
   5439 
   5440 
   5441 /* ------------------------------ */
   5442     .balign 64
   5443 .L_OP_AND_INT_2ADDR: /* 0xb5 */
   5444 /* File: armv6t2/OP_AND_INT_2ADDR.S */
   5445 /* File: armv6t2/binop2addr.S */
   5446     /*
   5447      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5448      * that specifies an instruction that performs "result = r0 op r1".
   5449      * This could be an ARM instruction or a function call.  (If the result
   5450      * comes back in a register other than r0, you can override "result".)
   5451      *
   5452      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5453      * vCC (r1).  Useful for integer division and modulus.
   5454      *
   5455      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5456      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5457      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5458      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5459      */
   5460     /* binop/2addr vA, vB */
   5461     mov     r3, rINST, lsr #12          @ r3<- B
   5462     ubfx    r9, rINST, #8, #4           @ r9<- A
   5463     GET_VREG(r1, r3)                    @ r1<- vB
   5464     GET_VREG(r0, r9)                    @ r0<- vA
   5465     .if 0
   5466     cmp     r1, #0                      @ is second operand zero?
   5467     beq     common_errDivideByZero
   5468     .endif
   5469     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5470 
   5471                                @ optional op; may set condition codes
   5472     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5473     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5474     SET_VREG(r0, r9)               @ vAA<- r0
   5475     GOTO_OPCODE(ip)                     @ jump to next instruction
   5476     /* 10-13 instructions */
   5477 
   5478 
   5479 /* ------------------------------ */
   5480     .balign 64
   5481 .L_OP_OR_INT_2ADDR: /* 0xb6 */
   5482 /* File: armv6t2/OP_OR_INT_2ADDR.S */
   5483 /* File: armv6t2/binop2addr.S */
   5484     /*
   5485      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5486      * that specifies an instruction that performs "result = r0 op r1".
   5487      * This could be an ARM instruction or a function call.  (If the result
   5488      * comes back in a register other than r0, you can override "result".)
   5489      *
   5490      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5491      * vCC (r1).  Useful for integer division and modulus.
   5492      *
   5493      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5494      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5495      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5496      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5497      */
   5498     /* binop/2addr vA, vB */
   5499     mov     r3, rINST, lsr #12          @ r3<- B
   5500     ubfx    r9, rINST, #8, #4           @ r9<- A
   5501     GET_VREG(r1, r3)                    @ r1<- vB
   5502     GET_VREG(r0, r9)                    @ r0<- vA
   5503     .if 0
   5504     cmp     r1, #0                      @ is second operand zero?
   5505     beq     common_errDivideByZero
   5506     .endif
   5507     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5508 
   5509                                @ optional op; may set condition codes
   5510     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5511     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5512     SET_VREG(r0, r9)               @ vAA<- r0
   5513     GOTO_OPCODE(ip)                     @ jump to next instruction
   5514     /* 10-13 instructions */
   5515 
   5516 
   5517 /* ------------------------------ */
   5518     .balign 64
   5519 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
   5520 /* File: armv6t2/OP_XOR_INT_2ADDR.S */
   5521 /* File: armv6t2/binop2addr.S */
   5522     /*
   5523      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5524      * that specifies an instruction that performs "result = r0 op r1".
   5525      * This could be an ARM instruction or a function call.  (If the result
   5526      * comes back in a register other than r0, you can override "result".)
   5527      *
   5528      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5529      * vCC (r1).  Useful for integer division and modulus.
   5530      *
   5531      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5532      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5533      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5534      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5535      */
   5536     /* binop/2addr vA, vB */
   5537     mov     r3, rINST, lsr #12          @ r3<- B
   5538     ubfx    r9, rINST, #8, #4           @ r9<- A
   5539     GET_VREG(r1, r3)                    @ r1<- vB
   5540     GET_VREG(r0, r9)                    @ r0<- vA
   5541     .if 0
   5542     cmp     r1, #0                      @ is second operand zero?
   5543     beq     common_errDivideByZero
   5544     .endif
   5545     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5546 
   5547                                @ optional op; may set condition codes
   5548     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5549     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5550     SET_VREG(r0, r9)               @ vAA<- r0
   5551     GOTO_OPCODE(ip)                     @ jump to next instruction
   5552     /* 10-13 instructions */
   5553 
   5554 
   5555 /* ------------------------------ */
   5556     .balign 64
   5557 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
   5558 /* File: armv6t2/OP_SHL_INT_2ADDR.S */
   5559 /* File: armv6t2/binop2addr.S */
   5560     /*
   5561      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5562      * that specifies an instruction that performs "result = r0 op r1".
   5563      * This could be an ARM instruction or a function call.  (If the result
   5564      * comes back in a register other than r0, you can override "result".)
   5565      *
   5566      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5567      * vCC (r1).  Useful for integer division and modulus.
   5568      *
   5569      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5570      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5571      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5572      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5573      */
   5574     /* binop/2addr vA, vB */
   5575     mov     r3, rINST, lsr #12          @ r3<- B
   5576     ubfx    r9, rINST, #8, #4           @ r9<- A
   5577     GET_VREG(r1, r3)                    @ r1<- vB
   5578     GET_VREG(r0, r9)                    @ r0<- vA
   5579     .if 0
   5580     cmp     r1, #0                      @ is second operand zero?
   5581     beq     common_errDivideByZero
   5582     .endif
   5583     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5584 
   5585     and     r1, r1, #31                           @ optional op; may set condition codes
   5586     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   5587     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5588     SET_VREG(r0, r9)               @ vAA<- r0
   5589     GOTO_OPCODE(ip)                     @ jump to next instruction
   5590     /* 10-13 instructions */
   5591 
   5592 
   5593 /* ------------------------------ */
   5594     .balign 64
   5595 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
   5596 /* File: armv6t2/OP_SHR_INT_2ADDR.S */
   5597 /* File: armv6t2/binop2addr.S */
   5598     /*
   5599      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5600      * that specifies an instruction that performs "result = r0 op r1".
   5601      * This could be an ARM instruction or a function call.  (If the result
   5602      * comes back in a register other than r0, you can override "result".)
   5603      *
   5604      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5605      * vCC (r1).  Useful for integer division and modulus.
   5606      *
   5607      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5608      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5609      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5610      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5611      */
   5612     /* binop/2addr vA, vB */
   5613     mov     r3, rINST, lsr #12          @ r3<- B
   5614     ubfx    r9, rINST, #8, #4           @ r9<- A
   5615     GET_VREG(r1, r3)                    @ r1<- vB
   5616     GET_VREG(r0, r9)                    @ r0<- vA
   5617     .if 0
   5618     cmp     r1, #0                      @ is second operand zero?
   5619     beq     common_errDivideByZero
   5620     .endif
   5621     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5622 
   5623     and     r1, r1, #31                           @ optional op; may set condition codes
   5624     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   5625     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5626     SET_VREG(r0, r9)               @ vAA<- r0
   5627     GOTO_OPCODE(ip)                     @ jump to next instruction
   5628     /* 10-13 instructions */
   5629 
   5630 
   5631 /* ------------------------------ */
   5632     .balign 64
   5633 .L_OP_USHR_INT_2ADDR: /* 0xba */
   5634 /* File: armv6t2/OP_USHR_INT_2ADDR.S */
   5635 /* File: armv6t2/binop2addr.S */
   5636     /*
   5637      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5638      * that specifies an instruction that performs "result = r0 op r1".
   5639      * This could be an ARM instruction or a function call.  (If the result
   5640      * comes back in a register other than r0, you can override "result".)
   5641      *
   5642      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5643      * vCC (r1).  Useful for integer division and modulus.
   5644      *
   5645      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5646      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5647      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5648      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5649      */
   5650     /* binop/2addr vA, vB */
   5651     mov     r3, rINST, lsr #12          @ r3<- B
   5652     ubfx    r9, rINST, #8, #4           @ r9<- A
   5653     GET_VREG(r1, r3)                    @ r1<- vB
   5654     GET_VREG(r0, r9)                    @ r0<- vA
   5655     .if 0
   5656     cmp     r1, #0                      @ is second operand zero?
   5657     beq     common_errDivideByZero
   5658     .endif
   5659     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5660 
   5661     and     r1, r1, #31                           @ optional op; may set condition codes
   5662     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   5663     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5664     SET_VREG(r0, r9)               @ vAA<- r0
   5665     GOTO_OPCODE(ip)                     @ jump to next instruction
   5666     /* 10-13 instructions */
   5667 
   5668 
   5669 /* ------------------------------ */
   5670     .balign 64
   5671 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
   5672 /* File: armv6t2/OP_ADD_LONG_2ADDR.S */
   5673 /* File: armv6t2/binopWide2addr.S */
   5674     /*
   5675      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5676      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5677      * This could be an ARM instruction or a function call.  (If the result
   5678      * comes back in a register other than r0, you can override "result".)
   5679      *
   5680      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5681      * vCC (r1).  Useful for integer division and modulus.
   5682      *
   5683      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5684      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5685      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5686      *      rem-double/2addr
   5687      */
   5688     /* binop/2addr vA, vB */
   5689     mov     r1, rINST, lsr #12          @ r1<- B
   5690     ubfx    r9, rINST, #8, #4           @ r9<- A
   5691     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5692     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5693     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5694     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5695     .if 0
   5696     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5697     beq     common_errDivideByZero
   5698     .endif
   5699     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5700 
   5701     adds    r0, r0, r2                           @ optional op; may set condition codes
   5702     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
   5703     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5704     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5705     GOTO_OPCODE(ip)                     @ jump to next instruction
   5706     /* 12-15 instructions */
   5707 
   5708 
   5709 /* ------------------------------ */
   5710     .balign 64
   5711 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
   5712 /* File: armv6t2/OP_SUB_LONG_2ADDR.S */
   5713 /* File: armv6t2/binopWide2addr.S */
   5714     /*
   5715      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5716      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5717      * This could be an ARM instruction or a function call.  (If the result
   5718      * comes back in a register other than r0, you can override "result".)
   5719      *
   5720      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5721      * vCC (r1).  Useful for integer division and modulus.
   5722      *
   5723      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5724      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5725      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5726      *      rem-double/2addr
   5727      */
   5728     /* binop/2addr vA, vB */
   5729     mov     r1, rINST, lsr #12          @ r1<- B
   5730     ubfx    r9, rINST, #8, #4           @ r9<- A
   5731     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5732     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5733     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5734     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5735     .if 0
   5736     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5737     beq     common_errDivideByZero
   5738     .endif
   5739     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5740 
   5741     subs    r0, r0, r2                           @ optional op; may set condition codes
   5742     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
   5743     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5744     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5745     GOTO_OPCODE(ip)                     @ jump to next instruction
   5746     /* 12-15 instructions */
   5747 
   5748 
   5749 /* ------------------------------ */
   5750     .balign 64
   5751 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
   5752 /* File: armv6t2/OP_MUL_LONG_2ADDR.S */
   5753     /*
   5754      * Signed 64-bit integer multiply, "/2addr" version.
   5755      *
   5756      * See OP_MUL_LONG for an explanation.
   5757      *
   5758      * We get a little tight on registers, so to avoid looking up &fp[A]
   5759      * again we stuff it into rINST.
   5760      */
   5761     /* mul-long/2addr vA, vB */
   5762     mov     r1, rINST, lsr #12          @ r1<- B
   5763     ubfx    r9, rINST, #8, #4           @ r9<- A
   5764     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5765     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
   5766     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5767     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
   5768     mul     ip, r2, r1                  @  ip<- ZxW
   5769     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
   5770     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
   5771     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
   5772     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5773     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
   5774     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5775     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
   5776     GOTO_OPCODE(ip)                     @ jump to next instruction
   5777 
   5778 /* ------------------------------ */
   5779     .balign 64
   5780 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
   5781 /* File: armv6t2/OP_DIV_LONG_2ADDR.S */
   5782 /* File: armv6t2/binopWide2addr.S */
   5783     /*
   5784      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5785      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5786      * This could be an ARM instruction or a function call.  (If the result
   5787      * comes back in a register other than r0, you can override "result".)
   5788      *
   5789      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5790      * vCC (r1).  Useful for integer division and modulus.
   5791      *
   5792      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5793      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5794      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5795      *      rem-double/2addr
   5796      */
   5797     /* binop/2addr vA, vB */
   5798     mov     r1, rINST, lsr #12          @ r1<- B
   5799     ubfx    r9, rINST, #8, #4           @ r9<- A
   5800     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5801     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5802     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5803     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5804     .if 1
   5805     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5806     beq     common_errDivideByZero
   5807     .endif
   5808     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5809 
   5810                                @ optional op; may set condition codes
   5811     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   5812     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5813     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5814     GOTO_OPCODE(ip)                     @ jump to next instruction
   5815     /* 12-15 instructions */
   5816 
   5817 
   5818 /* ------------------------------ */
   5819     .balign 64
   5820 .L_OP_REM_LONG_2ADDR: /* 0xbf */
   5821 /* File: armv6t2/OP_REM_LONG_2ADDR.S */
   5822 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
   5823 /* File: armv6t2/binopWide2addr.S */
   5824     /*
   5825      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5826      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5827      * This could be an ARM instruction or a function call.  (If the result
   5828      * comes back in a register other than r0, you can override "result".)
   5829      *
   5830      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5831      * vCC (r1).  Useful for integer division and modulus.
   5832      *
   5833      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5834      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5835      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5836      *      rem-double/2addr
   5837      */
   5838     /* binop/2addr vA, vB */
   5839     mov     r1, rINST, lsr #12          @ r1<- B
   5840     ubfx    r9, rINST, #8, #4           @ r9<- A
   5841     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5842     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5843     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5844     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5845     .if 1
   5846     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5847     beq     common_errDivideByZero
   5848     .endif
   5849     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5850 
   5851                                @ optional op; may set condition codes
   5852     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   5853     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5854     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
   5855     GOTO_OPCODE(ip)                     @ jump to next instruction
   5856     /* 12-15 instructions */
   5857 
   5858 
   5859 /* ------------------------------ */
   5860     .balign 64
   5861 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
   5862 /* File: armv6t2/OP_AND_LONG_2ADDR.S */
   5863 /* File: armv6t2/binopWide2addr.S */
   5864     /*
   5865      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5866      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5867      * This could be an ARM instruction or a function call.  (If the result
   5868      * comes back in a register other than r0, you can override "result".)
   5869      *
   5870      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5871      * vCC (r1).  Useful for integer division and modulus.
   5872      *
   5873      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5874      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5875      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5876      *      rem-double/2addr
   5877      */
   5878     /* binop/2addr vA, vB */
   5879     mov     r1, rINST, lsr #12          @ r1<- B
   5880     ubfx    r9, rINST, #8, #4           @ r9<- A
   5881     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5882     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5883     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5884     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5885     .if 0
   5886     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5887     beq     common_errDivideByZero
   5888     .endif
   5889     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5890 
   5891     and     r0, r0, r2                           @ optional op; may set condition codes
   5892     and     r1, r1, r3                              @ result<- op, r0-r3 changed
   5893     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5894     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5895     GOTO_OPCODE(ip)                     @ jump to next instruction
   5896     /* 12-15 instructions */
   5897 
   5898 
   5899 /* ------------------------------ */
   5900     .balign 64
   5901 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
   5902 /* File: armv6t2/OP_OR_LONG_2ADDR.S */
   5903 /* File: armv6t2/binopWide2addr.S */
   5904     /*
   5905      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5906      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5907      * This could be an ARM instruction or a function call.  (If the result
   5908      * comes back in a register other than r0, you can override "result".)
   5909      *
   5910      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5911      * vCC (r1).  Useful for integer division and modulus.
   5912      *
   5913      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5914      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5915      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5916      *      rem-double/2addr
   5917      */
   5918     /* binop/2addr vA, vB */
   5919     mov     r1, rINST, lsr #12          @ r1<- B
   5920     ubfx    r9, rINST, #8, #4           @ r9<- A
   5921     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5922     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5923     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5924     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5925     .if 0
   5926     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5927     beq     common_errDivideByZero
   5928     .endif
   5929     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5930 
   5931     orr     r0, r0, r2                           @ optional op; may set condition codes
   5932     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
   5933     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5934     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5935     GOTO_OPCODE(ip)                     @ jump to next instruction
   5936     /* 12-15 instructions */
   5937 
   5938 
   5939 /* ------------------------------ */
   5940     .balign 64
   5941 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
   5942 /* File: armv6t2/OP_XOR_LONG_2ADDR.S */
   5943 /* File: armv6t2/binopWide2addr.S */
   5944     /*
   5945      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5946      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5947      * This could be an ARM instruction or a function call.  (If the result
   5948      * comes back in a register other than r0, you can override "result".)
   5949      *
   5950      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5951      * vCC (r1).  Useful for integer division and modulus.
   5952      *
   5953      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5954      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5955      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5956      *      rem-double/2addr
   5957      */
   5958     /* binop/2addr vA, vB */
   5959     mov     r1, rINST, lsr #12          @ r1<- B
   5960     ubfx    r9, rINST, #8, #4           @ r9<- A
   5961     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5962     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5963     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5964     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5965     .if 0
   5966     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5967     beq     common_errDivideByZero
   5968     .endif
   5969     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5970 
   5971     eor     r0, r0, r2                           @ optional op; may set condition codes
   5972     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
   5973     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5974     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5975     GOTO_OPCODE(ip)                     @ jump to next instruction
   5976     /* 12-15 instructions */
   5977 
   5978 
   5979 /* ------------------------------ */
   5980     .balign 64
   5981 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
   5982 /* File: armv6t2/OP_SHL_LONG_2ADDR.S */
   5983     /*
   5984      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   5985      * 32-bit shift distance.
   5986      */
   5987     /* shl-long/2addr vA, vB */
   5988     mov     r3, rINST, lsr #12          @ r3<- B
   5989     ubfx    r9, rINST, #8, #4           @ r9<- A
   5990     GET_VREG(r2, r3)                    @ r2<- vB
   5991     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5992     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   5993     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5994 
   5995     mov     r1, r1, asl r2              @  r1<- r1 << r2
   5996     rsb     r3, r2, #32                 @  r3<- 32 - r2
   5997     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
   5998     subs    ip, r2, #32                 @  ip<- r2 - 32
   5999     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6000     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
   6001     mov     r0, r0, asl r2              @  r0<- r0 << r2
   6002     b       .LOP_SHL_LONG_2ADDR_finish
   6003 
   6004 /* ------------------------------ */
   6005     .balign 64
   6006 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
   6007 /* File: armv6t2/OP_SHR_LONG_2ADDR.S */
   6008     /*
   6009      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6010      * 32-bit shift distance.
   6011      */
   6012     /* shr-long/2addr vA, vB */
   6013     mov     r3, rINST, lsr #12          @ r3<- B
   6014     ubfx    r9, rINST, #8, #4           @ r9<- A
   6015     GET_VREG(r2, r3)                    @ r2<- vB
   6016     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6017     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6018     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6019 
   6020     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   6021     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6022     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   6023     subs    ip, r2, #32                 @  ip<- r2 - 32
   6024     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6025     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
   6026     mov     r1, r1, asr r2              @  r1<- r1 >> r2
   6027     b       .LOP_SHR_LONG_2ADDR_finish
   6028 
   6029 /* ------------------------------ */
   6030     .balign 64
   6031 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
   6032 /* File: armv6t2/OP_USHR_LONG_2ADDR.S */
   6033     /*
   6034      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6035      * 32-bit shift distance.
   6036      */
   6037     /* ushr-long/2addr vA, vB */
   6038     mov     r3, rINST, lsr #12          @ r3<- B
   6039     ubfx    r9, rINST, #8, #4           @ r9<- A
   6040     GET_VREG(r2, r3)                    @ r2<- vB
   6041     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6042     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6043     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6044 
   6045     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   6046     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6047     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   6048     subs    ip, r2, #32                 @  ip<- r2 - 32
   6049     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6050     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
   6051     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
   6052     b       .LOP_USHR_LONG_2ADDR_finish
   6053 
   6054 /* ------------------------------ */
   6055     .balign 64
   6056 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
   6057 /* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
   6058 /* File: arm-vfp/fbinop2addr.S */
   6059     /*
   6060      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6061      * an "instr" line that specifies an instruction that performs
   6062      * "s2 = s0 op s1".
   6063      *
   6064      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6065      */
   6066     /* binop/2addr vA, vB */
   6067     mov     r3, rINST, lsr #12          @ r3<- B
   6068     mov     r9, rINST, lsr #8           @ r9<- A+
   6069     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6070     and     r9, r9, #15                 @ r9<- A
   6071     flds    s1, [r3]                    @ s1<- vB
   6072     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6073     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6074     flds    s0, [r9]                    @ s0<- vA
   6075 
   6076     fadds   s2, s0, s1                              @ s2<- op
   6077     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6078     fsts    s2, [r9]                    @ vAA<- s2
   6079     GOTO_OPCODE(ip)                     @ jump to next instruction
   6080 
   6081 
   6082 /* ------------------------------ */
   6083     .balign 64
   6084 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
   6085 /* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
   6086 /* File: arm-vfp/fbinop2addr.S */
   6087     /*
   6088      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6089      * an "instr" line that specifies an instruction that performs
   6090      * "s2 = s0 op s1".
   6091      *
   6092      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6093      */
   6094     /* binop/2addr vA, vB */
   6095     mov     r3, rINST, lsr #12          @ r3<- B
   6096     mov     r9, rINST, lsr #8           @ r9<- A+
   6097     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6098     and     r9, r9, #15                 @ r9<- A
   6099     flds    s1, [r3]                    @ s1<- vB
   6100     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6101     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6102     flds    s0, [r9]                    @ s0<- vA
   6103 
   6104     fsubs   s2, s0, s1                              @ s2<- op
   6105     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6106     fsts    s2, [r9]                    @ vAA<- s2
   6107     GOTO_OPCODE(ip)                     @ jump to next instruction
   6108 
   6109 
   6110 /* ------------------------------ */
   6111     .balign 64
   6112 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
   6113 /* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
   6114 /* File: arm-vfp/fbinop2addr.S */
   6115     /*
   6116      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6117      * an "instr" line that specifies an instruction that performs
   6118      * "s2 = s0 op s1".
   6119      *
   6120      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6121      */
   6122     /* binop/2addr vA, vB */
   6123     mov     r3, rINST, lsr #12          @ r3<- B
   6124     mov     r9, rINST, lsr #8           @ r9<- A+
   6125     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6126     and     r9, r9, #15                 @ r9<- A
   6127     flds    s1, [r3]                    @ s1<- vB
   6128     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6129     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6130     flds    s0, [r9]                    @ s0<- vA
   6131 
   6132     fmuls   s2, s0, s1                              @ s2<- op
   6133     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6134     fsts    s2, [r9]                    @ vAA<- s2
   6135     GOTO_OPCODE(ip)                     @ jump to next instruction
   6136 
   6137 
   6138 /* ------------------------------ */
   6139     .balign 64
   6140 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
   6141 /* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
   6142 /* File: arm-vfp/fbinop2addr.S */
   6143     /*
   6144      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6145      * an "instr" line that specifies an instruction that performs
   6146      * "s2 = s0 op s1".
   6147      *
   6148      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6149      */
   6150     /* binop/2addr vA, vB */
   6151     mov     r3, rINST, lsr #12          @ r3<- B
   6152     mov     r9, rINST, lsr #8           @ r9<- A+
   6153     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6154     and     r9, r9, #15                 @ r9<- A
   6155     flds    s1, [r3]                    @ s1<- vB
   6156     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6157     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6158     flds    s0, [r9]                    @ s0<- vA
   6159 
   6160     fdivs   s2, s0, s1                              @ s2<- op
   6161     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6162     fsts    s2, [r9]                    @ vAA<- s2
   6163     GOTO_OPCODE(ip)                     @ jump to next instruction
   6164 
   6165 
   6166 /* ------------------------------ */
   6167     .balign 64
   6168 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
   6169 /* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
   6170 /* EABI doesn't define a float remainder function, but libm does */
   6171 /* File: armv6t2/binop2addr.S */
   6172     /*
   6173      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6174      * that specifies an instruction that performs "result = r0 op r1".
   6175      * This could be an ARM instruction or a function call.  (If the result
   6176      * comes back in a register other than r0, you can override "result".)
   6177      *
   6178      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6179      * vCC (r1).  Useful for integer division and modulus.
   6180      *
   6181      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6182      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6183      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6184      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6185      */
   6186     /* binop/2addr vA, vB */
   6187     mov     r3, rINST, lsr #12          @ r3<- B
   6188     ubfx    r9, rINST, #8, #4           @ r9<- A
   6189     GET_VREG(r1, r3)                    @ r1<- vB
   6190     GET_VREG(r0, r9)                    @ r0<- vA
   6191     .if 0
   6192     cmp     r1, #0                      @ is second operand zero?
   6193     beq     common_errDivideByZero
   6194     .endif
   6195     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6196 
   6197                                @ optional op; may set condition codes
   6198     bl      fmodf                              @ r0<- op, r0-r3 changed
   6199     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6200     SET_VREG(r0, r9)               @ vAA<- r0
   6201     GOTO_OPCODE(ip)                     @ jump to next instruction
   6202     /* 10-13 instructions */
   6203 
   6204 
   6205 /* ------------------------------ */
   6206     .balign 64
   6207 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
   6208 /* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
   6209 /* File: arm-vfp/fbinopWide2addr.S */
   6210     /*
   6211      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6212      * an "instr" line that specifies an instruction that performs
   6213      * "d2 = d0 op d1".
   6214      *
   6215      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6216      *      div-double/2addr
   6217      */
   6218     /* binop/2addr vA, vB */
   6219     mov     r3, rINST, lsr #12          @ r3<- B
   6220     mov     r9, rINST, lsr #8           @ r9<- A+
   6221     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6222     and     r9, r9, #15                 @ r9<- A
   6223     fldd    d1, [r3]                    @ d1<- vB
   6224     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6225     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6226     fldd    d0, [r9]                    @ d0<- vA
   6227 
   6228     faddd   d2, d0, d1                              @ d2<- op
   6229     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6230     fstd    d2, [r9]                    @ vAA<- d2
   6231     GOTO_OPCODE(ip)                     @ jump to next instruction
   6232 
   6233 
   6234 /* ------------------------------ */
   6235     .balign 64
   6236 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
   6237 /* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
   6238 /* File: arm-vfp/fbinopWide2addr.S */
   6239     /*
   6240      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6241      * an "instr" line that specifies an instruction that performs
   6242      * "d2 = d0 op d1".
   6243      *
   6244      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6245      *      div-double/2addr
   6246      */
   6247     /* binop/2addr vA, vB */
   6248     mov     r3, rINST, lsr #12          @ r3<- B
   6249     mov     r9, rINST, lsr #8           @ r9<- A+
   6250     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6251     and     r9, r9, #15                 @ r9<- A
   6252     fldd    d1, [r3]                    @ d1<- vB
   6253     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6254     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6255     fldd    d0, [r9]                    @ d0<- vA
   6256 
   6257     fsubd   d2, d0, d1                              @ d2<- op
   6258     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6259     fstd    d2, [r9]                    @ vAA<- d2
   6260     GOTO_OPCODE(ip)                     @ jump to next instruction
   6261 
   6262 
   6263 /* ------------------------------ */
   6264     .balign 64
   6265 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
   6266 /* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
   6267 /* File: arm-vfp/fbinopWide2addr.S */
   6268     /*
   6269      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6270      * an "instr" line that specifies an instruction that performs
   6271      * "d2 = d0 op d1".
   6272      *
   6273      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6274      *      div-double/2addr
   6275      */
   6276     /* binop/2addr vA, vB */
   6277     mov     r3, rINST, lsr #12          @ r3<- B
   6278     mov     r9, rINST, lsr #8           @ r9<- A+
   6279     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6280     and     r9, r9, #15                 @ r9<- A
   6281     fldd    d1, [r3]                    @ d1<- vB
   6282     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6283     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6284     fldd    d0, [r9]                    @ d0<- vA
   6285 
   6286     fmuld   d2, d0, d1                              @ d2<- op
   6287     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6288     fstd    d2, [r9]                    @ vAA<- d2
   6289     GOTO_OPCODE(ip)                     @ jump to next instruction
   6290 
   6291 
   6292 /* ------------------------------ */
   6293     .balign 64
   6294 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
   6295 /* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
   6296 /* File: arm-vfp/fbinopWide2addr.S */
   6297     /*
   6298      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6299      * an "instr" line that specifies an instruction that performs
   6300      * "d2 = d0 op d1".
   6301      *
   6302      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6303      *      div-double/2addr
   6304      */
   6305     /* binop/2addr vA, vB */
   6306     mov     r3, rINST, lsr #12          @ r3<- B
   6307     mov     r9, rINST, lsr #8           @ r9<- A+
   6308     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6309     and     r9, r9, #15                 @ r9<- A
   6310     fldd    d1, [r3]                    @ d1<- vB
   6311     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6312     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6313     fldd    d0, [r9]                    @ d0<- vA
   6314 
   6315     fdivd   d2, d0, d1                              @ d2<- op
   6316     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6317     fstd    d2, [r9]                    @ vAA<- d2
   6318     GOTO_OPCODE(ip)                     @ jump to next instruction
   6319 
   6320 
   6321 /* ------------------------------ */
   6322     .balign 64
   6323 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
   6324 /* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
   6325 /* EABI doesn't define a double remainder function, but libm does */
   6326 /* File: armv6t2/binopWide2addr.S */
   6327     /*
   6328      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6329      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6330      * This could be an ARM instruction or a function call.  (If the result
   6331      * comes back in a register other than r0, you can override "result".)
   6332      *
   6333      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6334      * vCC (r1).  Useful for integer division and modulus.
   6335      *
   6336      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6337      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6338      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6339      *      rem-double/2addr
   6340      */
   6341     /* binop/2addr vA, vB */
   6342     mov     r1, rINST, lsr #12          @ r1<- B
   6343     ubfx    r9, rINST, #8, #4           @ r9<- A
   6344     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6345     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6346     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6347     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6348     .if 0
   6349     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6350     beq     common_errDivideByZero
   6351     .endif
   6352     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6353 
   6354                                @ optional op; may set condition codes
   6355     bl      fmod                              @ result<- op, r0-r3 changed
   6356     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6357     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6358     GOTO_OPCODE(ip)                     @ jump to next instruction
   6359     /* 12-15 instructions */
   6360 
   6361 
   6362 /* ------------------------------ */
   6363     .balign 64
   6364 .L_OP_ADD_INT_LIT16: /* 0xd0 */
   6365 /* File: armv6t2/OP_ADD_INT_LIT16.S */
   6366 /* File: armv6t2/binopLit16.S */
   6367     /*
   6368      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6369      * that specifies an instruction that performs "result = r0 op r1".
   6370      * This could be an ARM instruction or a function call.  (If the result
   6371      * comes back in a register other than r0, you can override "result".)
   6372      *
   6373      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6374      * vCC (r1).  Useful for integer division and modulus.
   6375      *
   6376      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6377      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6378      */
   6379     /* binop/lit16 vA, vB, #+CCCC */
   6380     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6381     mov     r2, rINST, lsr #12          @ r2<- B
   6382     ubfx    r9, rINST, #8, #4           @ r9<- A
   6383     GET_VREG(r0, r2)                    @ r0<- vB
   6384     .if 0
   6385     cmp     r1, #0                      @ is second operand zero?
   6386     beq     common_errDivideByZero
   6387     .endif
   6388     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6389 
   6390     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6391     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6392     SET_VREG(r0, r9)               @ vAA<- r0
   6393     GOTO_OPCODE(ip)                     @ jump to next instruction
   6394     /* 10-13 instructions */
   6395 
   6396 
   6397 /* ------------------------------ */
   6398     .balign 64
   6399 .L_OP_RSUB_INT: /* 0xd1 */
   6400 /* File: armv6t2/OP_RSUB_INT.S */
   6401 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
   6402 /* File: armv6t2/binopLit16.S */
   6403     /*
   6404      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6405      * that specifies an instruction that performs "result = r0 op r1".
   6406      * This could be an ARM instruction or a function call.  (If the result
   6407      * comes back in a register other than r0, you can override "result".)
   6408      *
   6409      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6410      * vCC (r1).  Useful for integer division and modulus.
   6411      *
   6412      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6413      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6414      */
   6415     /* binop/lit16 vA, vB, #+CCCC */
   6416     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6417     mov     r2, rINST, lsr #12          @ r2<- B
   6418     ubfx    r9, rINST, #8, #4           @ r9<- A
   6419     GET_VREG(r0, r2)                    @ r0<- vB
   6420     .if 0
   6421     cmp     r1, #0                      @ is second operand zero?
   6422     beq     common_errDivideByZero
   6423     .endif
   6424     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6425 
   6426     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6427     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6428     SET_VREG(r0, r9)               @ vAA<- r0
   6429     GOTO_OPCODE(ip)                     @ jump to next instruction
   6430     /* 10-13 instructions */
   6431 
   6432 
   6433 /* ------------------------------ */
   6434     .balign 64
   6435 .L_OP_MUL_INT_LIT16: /* 0xd2 */
   6436 /* File: armv6t2/OP_MUL_INT_LIT16.S */
   6437 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   6438 /* File: armv6t2/binopLit16.S */
   6439     /*
   6440      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6441      * that specifies an instruction that performs "result = r0 op r1".
   6442      * This could be an ARM instruction or a function call.  (If the result
   6443      * comes back in a register other than r0, you can override "result".)
   6444      *
   6445      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6446      * vCC (r1).  Useful for integer division and modulus.
   6447      *
   6448      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6449      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6450      */
   6451     /* binop/lit16 vA, vB, #+CCCC */
   6452     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6453     mov     r2, rINST, lsr #12          @ r2<- B
   6454     ubfx    r9, rINST, #8, #4           @ r9<- A
   6455     GET_VREG(r0, r2)                    @ r0<- vB
   6456     .if 0
   6457     cmp     r1, #0                      @ is second operand zero?
   6458     beq     common_errDivideByZero
   6459     .endif
   6460     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6461 
   6462     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   6463     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6464     SET_VREG(r0, r9)               @ vAA<- r0
   6465     GOTO_OPCODE(ip)                     @ jump to next instruction
   6466     /* 10-13 instructions */
   6467 
   6468 
   6469 /* ------------------------------ */
   6470     .balign 64
   6471 .L_OP_DIV_INT_LIT16: /* 0xd3 */
   6472 /* File: armv6t2/OP_DIV_INT_LIT16.S */
   6473 /* File: armv6t2/binopLit16.S */
   6474     /*
   6475      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6476      * that specifies an instruction that performs "result = r0 op r1".
   6477      * This could be an ARM instruction or a function call.  (If the result
   6478      * comes back in a register other than r0, you can override "result".)
   6479      *
   6480      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6481      * vCC (r1).  Useful for integer division and modulus.
   6482      *
   6483      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6484      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6485      */
   6486     /* binop/lit16 vA, vB, #+CCCC */
   6487     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6488     mov     r2, rINST, lsr #12          @ r2<- B
   6489     ubfx    r9, rINST, #8, #4           @ r9<- A
   6490     GET_VREG(r0, r2)                    @ r0<- vB
   6491     .if 1
   6492     cmp     r1, #0                      @ is second operand zero?
   6493     beq     common_errDivideByZero
   6494     .endif
   6495     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6496 
   6497     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   6498     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6499     SET_VREG(r0, r9)               @ vAA<- r0
   6500     GOTO_OPCODE(ip)                     @ jump to next instruction
   6501     /* 10-13 instructions */
   6502 
   6503 
   6504 /* ------------------------------ */
   6505     .balign 64
   6506 .L_OP_REM_INT_LIT16: /* 0xd4 */
   6507 /* File: armv6t2/OP_REM_INT_LIT16.S */
   6508 /* idivmod returns quotient in r0 and remainder in r1 */
   6509 /* File: armv6t2/binopLit16.S */
   6510     /*
   6511      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6512      * that specifies an instruction that performs "result = r0 op r1".
   6513      * This could be an ARM instruction or a function call.  (If the result
   6514      * comes back in a register other than r0, you can override "result".)
   6515      *
   6516      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6517      * vCC (r1).  Useful for integer division and modulus.
   6518      *
   6519      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6520      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6521      */
   6522     /* binop/lit16 vA, vB, #+CCCC */
   6523     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6524     mov     r2, rINST, lsr #12          @ r2<- B
   6525     ubfx    r9, rINST, #8, #4           @ r9<- A
   6526     GET_VREG(r0, r2)                    @ r0<- vB
   6527     .if 1
   6528     cmp     r1, #0                      @ is second operand zero?
   6529     beq     common_errDivideByZero
   6530     .endif
   6531     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6532 
   6533     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   6534     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6535     SET_VREG(r1, r9)               @ vAA<- r1
   6536     GOTO_OPCODE(ip)                     @ jump to next instruction
   6537     /* 10-13 instructions */
   6538 
   6539 
   6540 /* ------------------------------ */
   6541     .balign 64
   6542 .L_OP_AND_INT_LIT16: /* 0xd5 */
   6543 /* File: armv6t2/OP_AND_INT_LIT16.S */
   6544 /* File: armv6t2/binopLit16.S */
   6545     /*
   6546      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6547      * that specifies an instruction that performs "result = r0 op r1".
   6548      * This could be an ARM instruction or a function call.  (If the result
   6549      * comes back in a register other than r0, you can override "result".)
   6550      *
   6551      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6552      * vCC (r1).  Useful for integer division and modulus.
   6553      *
   6554      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6555      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6556      */
   6557     /* binop/lit16 vA, vB, #+CCCC */
   6558     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6559     mov     r2, rINST, lsr #12          @ r2<- B
   6560     ubfx    r9, rINST, #8, #4           @ r9<- A
   6561     GET_VREG(r0, r2)                    @ r0<- vB
   6562     .if 0
   6563     cmp     r1, #0                      @ is second operand zero?
   6564     beq     common_errDivideByZero
   6565     .endif
   6566     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6567 
   6568     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6569     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6570     SET_VREG(r0, r9)               @ vAA<- r0
   6571     GOTO_OPCODE(ip)                     @ jump to next instruction
   6572     /* 10-13 instructions */
   6573 
   6574 
   6575 /* ------------------------------ */
   6576     .balign 64
   6577 .L_OP_OR_INT_LIT16: /* 0xd6 */
   6578 /* File: armv6t2/OP_OR_INT_LIT16.S */
   6579 /* File: armv6t2/binopLit16.S */
   6580     /*
   6581      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6582      * that specifies an instruction that performs "result = r0 op r1".
   6583      * This could be an ARM instruction or a function call.  (If the result
   6584      * comes back in a register other than r0, you can override "result".)
   6585      *
   6586      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6587      * vCC (r1).  Useful for integer division and modulus.
   6588      *
   6589      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6590      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6591      */
   6592     /* binop/lit16 vA, vB, #+CCCC */
   6593     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6594     mov     r2, rINST, lsr #12          @ r2<- B
   6595     ubfx    r9, rINST, #8, #4           @ r9<- A
   6596     GET_VREG(r0, r2)                    @ r0<- vB
   6597     .if 0
   6598     cmp     r1, #0                      @ is second operand zero?
   6599     beq     common_errDivideByZero
   6600     .endif
   6601     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6602 
   6603     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6604     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6605     SET_VREG(r0, r9)               @ vAA<- r0
   6606     GOTO_OPCODE(ip)                     @ jump to next instruction
   6607     /* 10-13 instructions */
   6608 
   6609 
   6610 /* ------------------------------ */
   6611     .balign 64
   6612 .L_OP_XOR_INT_LIT16: /* 0xd7 */
   6613 /* File: armv6t2/OP_XOR_INT_LIT16.S */
   6614 /* File: armv6t2/binopLit16.S */
   6615     /*
   6616      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6617      * that specifies an instruction that performs "result = r0 op r1".
   6618      * This could be an ARM instruction or a function call.  (If the result
   6619      * comes back in a register other than r0, you can override "result".)
   6620      *
   6621      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6622      * vCC (r1).  Useful for integer division and modulus.
   6623      *
   6624      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6625      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6626      */
   6627     /* binop/lit16 vA, vB, #+CCCC */
   6628     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6629     mov     r2, rINST, lsr #12          @ r2<- B
   6630     ubfx    r9, rINST, #8, #4           @ r9<- A
   6631     GET_VREG(r0, r2)                    @ r0<- vB
   6632     .if 0
   6633     cmp     r1, #0                      @ is second operand zero?
   6634     beq     common_errDivideByZero
   6635     .endif
   6636     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6637 
   6638     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6639     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6640     SET_VREG(r0, r9)               @ vAA<- r0
   6641     GOTO_OPCODE(ip)                     @ jump to next instruction
   6642     /* 10-13 instructions */
   6643 
   6644 
   6645 /* ------------------------------ */
   6646     .balign 64
   6647 .L_OP_ADD_INT_LIT8: /* 0xd8 */
   6648 /* File: armv5te/OP_ADD_INT_LIT8.S */
   6649 /* File: armv5te/binopLit8.S */
   6650     /*
   6651      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6652      * that specifies an instruction that performs "result = r0 op r1".
   6653      * This could be an ARM instruction or a function call.  (If the result
   6654      * comes back in a register other than r0, you can override "result".)
   6655      *
   6656      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6657      * vCC (r1).  Useful for integer division and modulus.
   6658      *
   6659      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6660      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6661      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6662      */
   6663     /* binop/lit8 vAA, vBB, #+CC */
   6664     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6665     mov     r9, rINST, lsr #8           @ r9<- AA
   6666     and     r2, r3, #255                @ r2<- BB
   6667     GET_VREG(r0, r2)                    @ r0<- vBB
   6668     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6669     .if 0
   6670     @cmp     r1, #0                      @ is second operand zero?
   6671     beq     common_errDivideByZero
   6672     .endif
   6673     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6674 
   6675                                @ optional op; may set condition codes
   6676     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6677     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6678     SET_VREG(r0, r9)               @ vAA<- r0
   6679     GOTO_OPCODE(ip)                     @ jump to next instruction
   6680     /* 10-12 instructions */
   6681 
   6682 
   6683 /* ------------------------------ */
   6684     .balign 64
   6685 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
   6686 /* File: armv5te/OP_RSUB_INT_LIT8.S */
   6687 /* File: armv5te/binopLit8.S */
   6688     /*
   6689      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6690      * that specifies an instruction that performs "result = r0 op r1".
   6691      * This could be an ARM instruction or a function call.  (If the result
   6692      * comes back in a register other than r0, you can override "result".)
   6693      *
   6694      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6695      * vCC (r1).  Useful for integer division and modulus.
   6696      *
   6697      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6698      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6699      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6700      */
   6701     /* binop/lit8 vAA, vBB, #+CC */
   6702     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6703     mov     r9, rINST, lsr #8           @ r9<- AA
   6704     and     r2, r3, #255                @ r2<- BB
   6705     GET_VREG(r0, r2)                    @ r0<- vBB
   6706     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6707     .if 0
   6708     @cmp     r1, #0                      @ is second operand zero?
   6709     beq     common_errDivideByZero
   6710     .endif
   6711     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6712 
   6713                                @ optional op; may set condition codes
   6714     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6715     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6716     SET_VREG(r0, r9)               @ vAA<- r0
   6717     GOTO_OPCODE(ip)                     @ jump to next instruction
   6718     /* 10-12 instructions */
   6719 
   6720 
   6721 /* ------------------------------ */
   6722     .balign 64
   6723 .L_OP_MUL_INT_LIT8: /* 0xda */
   6724 /* File: armv5te/OP_MUL_INT_LIT8.S */
   6725 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   6726 /* File: armv5te/binopLit8.S */
   6727     /*
   6728      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6729      * that specifies an instruction that performs "result = r0 op r1".
   6730      * This could be an ARM instruction or a function call.  (If the result
   6731      * comes back in a register other than r0, you can override "result".)
   6732      *
   6733      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6734      * vCC (r1).  Useful for integer division and modulus.
   6735      *
   6736      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6737      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6738      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6739      */
   6740     /* binop/lit8 vAA, vBB, #+CC */
   6741     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6742     mov     r9, rINST, lsr #8           @ r9<- AA
   6743     and     r2, r3, #255                @ r2<- BB
   6744     GET_VREG(r0, r2)                    @ r0<- vBB
   6745     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6746     .if 0
   6747     @cmp     r1, #0                      @ is second operand zero?
   6748     beq     common_errDivideByZero
   6749     .endif
   6750     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6751 
   6752                                @ optional op; may set condition codes
   6753     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   6754     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6755     SET_VREG(r0, r9)               @ vAA<- r0
   6756     GOTO_OPCODE(ip)                     @ jump to next instruction
   6757     /* 10-12 instructions */
   6758 
   6759 
   6760 /* ------------------------------ */
   6761     .balign 64
   6762 .L_OP_DIV_INT_LIT8: /* 0xdb */
   6763 /* File: armv5te/OP_DIV_INT_LIT8.S */
   6764 /* File: armv5te/binopLit8.S */
   6765     /*
   6766      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6767      * that specifies an instruction that performs "result = r0 op r1".
   6768      * This could be an ARM instruction or a function call.  (If the result
   6769      * comes back in a register other than r0, you can override "result".)
   6770      *
   6771      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6772      * vCC (r1).  Useful for integer division and modulus.
   6773      *
   6774      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6775      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6776      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6777      */
   6778     /* binop/lit8 vAA, vBB, #+CC */
   6779     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6780     mov     r9, rINST, lsr #8           @ r9<- AA
   6781     and     r2, r3, #255                @ r2<- BB
   6782     GET_VREG(r0, r2)                    @ r0<- vBB
   6783     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6784     .if 1
   6785     @cmp     r1, #0                      @ is second operand zero?
   6786     beq     common_errDivideByZero
   6787     .endif
   6788     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6789 
   6790                                @ optional op; may set condition codes
   6791     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   6792     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6793     SET_VREG(r0, r9)               @ vAA<- r0
   6794     GOTO_OPCODE(ip)                     @ jump to next instruction
   6795     /* 10-12 instructions */
   6796 
   6797 
   6798 /* ------------------------------ */
   6799     .balign 64
   6800 .L_OP_REM_INT_LIT8: /* 0xdc */
   6801 /* File: armv5te/OP_REM_INT_LIT8.S */
   6802 /* idivmod returns quotient in r0 and remainder in r1 */
   6803 /* File: armv5te/binopLit8.S */
   6804     /*
   6805      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6806      * that specifies an instruction that performs "result = r0 op r1".
   6807      * This could be an ARM instruction or a function call.  (If the result
   6808      * comes back in a register other than r0, you can override "result".)
   6809      *
   6810      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6811      * vCC (r1).  Useful for integer division and modulus.
   6812      *
   6813      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6814      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6815      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6816      */
   6817     /* binop/lit8 vAA, vBB, #+CC */
   6818     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6819     mov     r9, rINST, lsr #8           @ r9<- AA
   6820     and     r2, r3, #255                @ r2<- BB
   6821     GET_VREG(r0, r2)                    @ r0<- vBB
   6822     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6823     .if 1
   6824     @cmp     r1, #0                      @ is second operand zero?
   6825     beq     common_errDivideByZero
   6826     .endif
   6827     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6828 
   6829                                @ optional op; may set condition codes
   6830     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   6831     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6832     SET_VREG(r1, r9)               @ vAA<- r1
   6833     GOTO_OPCODE(ip)                     @ jump to next instruction
   6834     /* 10-12 instructions */
   6835 
   6836 
   6837 /* ------------------------------ */
   6838     .balign 64
   6839 .L_OP_AND_INT_LIT8: /* 0xdd */
   6840 /* File: armv5te/OP_AND_INT_LIT8.S */
   6841 /* File: armv5te/binopLit8.S */
   6842     /*
   6843      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6844      * that specifies an instruction that performs "result = r0 op r1".
   6845      * This could be an ARM instruction or a function call.  (If the result
   6846      * comes back in a register other than r0, you can override "result".)
   6847      *
   6848      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6849      * vCC (r1).  Useful for integer division and modulus.
   6850      *
   6851      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6852      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6853      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6854      */
   6855     /* binop/lit8 vAA, vBB, #+CC */
   6856     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6857     mov     r9, rINST, lsr #8           @ r9<- AA
   6858     and     r2, r3, #255                @ r2<- BB
   6859     GET_VREG(r0, r2)                    @ r0<- vBB
   6860     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6861     .if 0
   6862     @cmp     r1, #0                      @ is second operand zero?
   6863     beq     common_errDivideByZero
   6864     .endif
   6865     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6866 
   6867                                @ optional op; may set condition codes
   6868     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6869     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6870     SET_VREG(r0, r9)               @ vAA<- r0
   6871     GOTO_OPCODE(ip)                     @ jump to next instruction
   6872     /* 10-12 instructions */
   6873 
   6874 
   6875 /* ------------------------------ */
   6876     .balign 64
   6877 .L_OP_OR_INT_LIT8: /* 0xde */
   6878 /* File: armv5te/OP_OR_INT_LIT8.S */
   6879 /* File: armv5te/binopLit8.S */
   6880     /*
   6881      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6882      * that specifies an instruction that performs "result = r0 op r1".
   6883      * This could be an ARM instruction or a function call.  (If the result
   6884      * comes back in a register other than r0, you can override "result".)
   6885      *
   6886      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6887      * vCC (r1).  Useful for integer division and modulus.
   6888      *
   6889      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6890      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6891      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6892      */
   6893     /* binop/lit8 vAA, vBB, #+CC */
   6894     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6895     mov     r9, rINST, lsr #8           @ r9<- AA
   6896     and     r2, r3, #255                @ r2<- BB
   6897     GET_VREG(r0, r2)                    @ r0<- vBB
   6898     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6899     .if 0
   6900     @cmp     r1, #0                      @ is second operand zero?
   6901     beq     common_errDivideByZero
   6902     .endif
   6903     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6904 
   6905                                @ optional op; may set condition codes
   6906     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6907     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6908     SET_VREG(r0, r9)               @ vAA<- r0
   6909     GOTO_OPCODE(ip)                     @ jump to next instruction
   6910     /* 10-12 instructions */
   6911 
   6912 
   6913 /* ------------------------------ */
   6914     .balign 64
   6915 .L_OP_XOR_INT_LIT8: /* 0xdf */
   6916 /* File: armv5te/OP_XOR_INT_LIT8.S */
   6917 /* File: armv5te/binopLit8.S */
   6918     /*
   6919      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6920      * that specifies an instruction that performs "result = r0 op r1".
   6921      * This could be an ARM instruction or a function call.  (If the result
   6922      * comes back in a register other than r0, you can override "result".)
   6923      *
   6924      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6925      * vCC (r1).  Useful for integer division and modulus.
   6926      *
   6927      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6928      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6929      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6930      */
   6931     /* binop/lit8 vAA, vBB, #+CC */
   6932     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6933     mov     r9, rINST, lsr #8           @ r9<- AA
   6934     and     r2, r3, #255                @ r2<- BB
   6935     GET_VREG(r0, r2)                    @ r0<- vBB
   6936     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6937     .if 0
   6938     @cmp     r1, #0                      @ is second operand zero?
   6939     beq     common_errDivideByZero
   6940     .endif
   6941     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6942 
   6943                                @ optional op; may set condition codes
   6944     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6945     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6946     SET_VREG(r0, r9)               @ vAA<- r0
   6947     GOTO_OPCODE(ip)                     @ jump to next instruction
   6948     /* 10-12 instructions */
   6949 
   6950 
   6951 /* ------------------------------ */
   6952     .balign 64
   6953 .L_OP_SHL_INT_LIT8: /* 0xe0 */
   6954 /* File: armv5te/OP_SHL_INT_LIT8.S */
   6955 /* File: armv5te/binopLit8.S */
   6956     /*
   6957      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6958      * that specifies an instruction that performs "result = r0 op r1".
   6959      * This could be an ARM instruction or a function call.  (If the result
   6960      * comes back in a register other than r0, you can override "result".)
   6961      *
   6962      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6963      * vCC (r1).  Useful for integer division and modulus.
   6964      *
   6965      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6966      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6967      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6968      */
   6969     /* binop/lit8 vAA, vBB, #+CC */
   6970     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6971     mov     r9, rINST, lsr #8           @ r9<- AA
   6972     and     r2, r3, #255                @ r2<- BB
   6973     GET_VREG(r0, r2)                    @ r0<- vBB
   6974     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6975     .if 0
   6976     @cmp     r1, #0                      @ is second operand zero?
   6977     beq     common_errDivideByZero
   6978     .endif
   6979     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6980 
   6981     and     r1, r1, #31                           @ optional op; may set condition codes
   6982     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   6983     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6984     SET_VREG(r0, r9)               @ vAA<- r0
   6985     GOTO_OPCODE(ip)                     @ jump to next instruction
   6986     /* 10-12 instructions */
   6987 
   6988 
   6989 /* ------------------------------ */
   6990     .balign 64
   6991 .L_OP_SHR_INT_LIT8: /* 0xe1 */
   6992 /* File: armv5te/OP_SHR_INT_LIT8.S */
   6993 /* File: armv5te/binopLit8.S */
   6994     /*
   6995      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6996      * that specifies an instruction that performs "result = r0 op r1".
   6997      * This could be an ARM instruction or a function call.  (If the result
   6998      * comes back in a register other than r0, you can override "result".)
   6999      *
   7000      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7001      * vCC (r1).  Useful for integer division and modulus.
   7002      *
   7003      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7004      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7005      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7006      */
   7007     /* binop/lit8 vAA, vBB, #+CC */
   7008     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7009     mov     r9, rINST, lsr #8           @ r9<- AA
   7010     and     r2, r3, #255                @ r2<- BB
   7011     GET_VREG(r0, r2)                    @ r0<- vBB
   7012     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7013     .if 0
   7014     @cmp     r1, #0                      @ is second operand zero?
   7015     beq     common_errDivideByZero
   7016     .endif
   7017     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7018 
   7019     and     r1, r1, #31                           @ optional op; may set condition codes
   7020     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   7021     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7022     SET_VREG(r0, r9)               @ vAA<- r0
   7023     GOTO_OPCODE(ip)                     @ jump to next instruction
   7024     /* 10-12 instructions */
   7025 
   7026 
   7027 /* ------------------------------ */
   7028     .balign 64
   7029 .L_OP_USHR_INT_LIT8: /* 0xe2 */
   7030 /* File: armv5te/OP_USHR_INT_LIT8.S */
   7031 /* File: armv5te/binopLit8.S */
   7032     /*
   7033      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7034      * that specifies an instruction that performs "result = r0 op r1".
   7035      * This could be an ARM instruction or a function call.  (If the result
   7036      * comes back in a register other than r0, you can override "result".)
   7037      *
   7038      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7039      * vCC (r1).  Useful for integer division and modulus.
   7040      *
   7041      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7042      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7043      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7044      */
   7045     /* binop/lit8 vAA, vBB, #+CC */
   7046     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7047     mov     r9, rINST, lsr #8           @ r9<- AA
   7048     and     r2, r3, #255                @ r2<- BB
   7049     GET_VREG(r0, r2)                    @ r0<- vBB
   7050     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7051     .if 0
   7052     @cmp     r1, #0                      @ is second operand zero?
   7053     beq     common_errDivideByZero
   7054     .endif
   7055     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7056 
   7057     and     r1, r1, #31                           @ optional op; may set condition codes
   7058     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   7059     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7060     SET_VREG(r0, r9)               @ vAA<- r0
   7061     GOTO_OPCODE(ip)                     @ jump to next instruction
   7062     /* 10-12 instructions */
   7063 
   7064 
   7065 /* ------------------------------ */
   7066     .balign 64
   7067 .L_OP_IGET_VOLATILE: /* 0xe3 */
   7068 /* File: armv5te/OP_IGET_VOLATILE.S */
   7069 /* File: armv5te/OP_IGET.S */
   7070     /*
   7071      * General 32-bit instance field get.
   7072      *
   7073      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   7074      */
   7075     /* op vA, vB, field@CCCC */
   7076     mov     r0, rINST, lsr #12          @ r0<- B
   7077     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7078     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7079     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7080     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7081     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7082     cmp     r0, #0                      @ is resolved entry null?
   7083     bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
   7084 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7085     EXPORT_PC()                         @ resolve() could throw
   7086     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7087     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7088     cmp     r0, #0
   7089     bne     .LOP_IGET_VOLATILE_finish
   7090     b       common_exceptionThrown
   7091 
   7092 
   7093 /* ------------------------------ */
   7094     .balign 64
   7095 .L_OP_IPUT_VOLATILE: /* 0xe4 */
   7096 /* File: armv5te/OP_IPUT_VOLATILE.S */
   7097 /* File: armv5te/OP_IPUT.S */
   7098     /*
   7099      * General 32-bit instance field put.
   7100      *
   7101      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   7102      */
   7103     /* op vA, vB, field@CCCC */
   7104     mov     r0, rINST, lsr #12          @ r0<- B
   7105     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7106     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7107     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7108     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7109     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7110     cmp     r0, #0                      @ is resolved entry null?
   7111     bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
   7112 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7113     EXPORT_PC()                         @ resolve() could throw
   7114     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7115     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7116     cmp     r0, #0                      @ success?
   7117     bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
   7118     b       common_exceptionThrown
   7119 
   7120 
   7121 /* ------------------------------ */
   7122     .balign 64
   7123 .L_OP_SGET_VOLATILE: /* 0xe5 */
   7124 /* File: armv5te/OP_SGET_VOLATILE.S */
   7125 /* File: armv5te/OP_SGET.S */
   7126     /*
   7127      * General 32-bit SGET handler.
   7128      *
   7129      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   7130      */
   7131     /* op vAA, field@BBBB */
   7132     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7133     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7134     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7135     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7136     cmp     r0, #0                      @ is resolved entry null?
   7137     beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
   7138 .LOP_SGET_VOLATILE_finish: @ field ptr in r0
   7139     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   7140     SMP_DMB                            @ acquiring load
   7141     mov     r2, rINST, lsr #8           @ r2<- AA
   7142     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7143     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   7144     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7145     GOTO_OPCODE(ip)                     @ jump to next instruction
   7146 
   7147 
   7148 /* ------------------------------ */
   7149     .balign 64
   7150 .L_OP_SPUT_VOLATILE: /* 0xe6 */
   7151 /* File: armv5te/OP_SPUT_VOLATILE.S */
   7152 /* File: armv5te/OP_SPUT.S */
   7153     /*
   7154      * General 32-bit SPUT handler.
   7155      *
   7156      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   7157      */
   7158     /* op vAA, field@BBBB */
   7159     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7160     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7161     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7162     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7163     cmp     r0, #0                      @ is resolved entry null?
   7164     beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
   7165 .LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
   7166     mov     r2, rINST, lsr #8           @ r2<- AA
   7167     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7168     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   7169     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7170     SMP_DMB                            @ releasing store
   7171     str     r1, [r0, #offStaticField_value] @ field<- vAA
   7172     GOTO_OPCODE(ip)                     @ jump to next instruction
   7173 
   7174 
   7175 /* ------------------------------ */
   7176     .balign 64
   7177 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
   7178 /* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
   7179 /* File: armv5te/OP_IGET.S */
   7180     /*
   7181      * General 32-bit instance field get.
   7182      *
   7183      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   7184      */
   7185     /* op vA, vB, field@CCCC */
   7186     mov     r0, rINST, lsr #12          @ r0<- B
   7187     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7188     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7189     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7190     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7191     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7192     cmp     r0, #0                      @ is resolved entry null?
   7193     bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
   7194 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7195     EXPORT_PC()                         @ resolve() could throw
   7196     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7197     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7198     cmp     r0, #0
   7199     bne     .LOP_IGET_OBJECT_VOLATILE_finish
   7200     b       common_exceptionThrown
   7201 
   7202 
   7203 /* ------------------------------ */
   7204     .balign 64
   7205 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
   7206 /* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
   7207 /* File: armv5te/OP_IGET_WIDE.S */
   7208     /*
   7209      * Wide 32-bit instance field get.
   7210      */
   7211     /* iget-wide vA, vB, field@CCCC */
   7212     mov     r0, rINST, lsr #12          @ r0<- B
   7213     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7214     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7215     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   7216     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7217     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7218     cmp     r0, #0                      @ is resolved entry null?
   7219     bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
   7220 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   7221     EXPORT_PC()                         @ resolve() could throw
   7222     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7223     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7224     cmp     r0, #0
   7225     bne     .LOP_IGET_WIDE_VOLATILE_finish
   7226     b       common_exceptionThrown
   7227 
   7228 
   7229 /* ------------------------------ */
   7230     .balign 64
   7231 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
   7232 /* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
   7233 /* File: armv5te/OP_IPUT_WIDE.S */
   7234     /* iput-wide vA, vB, field@CCCC */
   7235     mov     r0, rINST, lsr #12          @ r0<- B
   7236     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7237     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7238     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   7239     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7240     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7241     cmp     r0, #0                      @ is resolved entry null?
   7242     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
   7243 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   7244     EXPORT_PC()                         @ resolve() could throw
   7245     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7246     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7247     cmp     r0, #0                      @ success?
   7248     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
   7249     b       common_exceptionThrown
   7250 
   7251 
   7252 /* ------------------------------ */
   7253     .balign 64
   7254 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
   7255 /* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
   7256 /* File: armv5te/OP_SGET_WIDE.S */
   7257     /*
   7258      * 64-bit SGET handler.
   7259      */
   7260     /* sget-wide vAA, field@BBBB */
   7261     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7262     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7263     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7264     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7265     cmp     r0, #0                      @ is resolved entry null?
   7266     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
   7267 .LOP_SGET_WIDE_VOLATILE_finish:
   7268     mov     r9, rINST, lsr #8           @ r9<- AA
   7269     .if 1
   7270     add     r0, r0, #offStaticField_value @ r0<- pointer to data
   7271     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   7272     .else
   7273     ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
   7274     .endif
   7275     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   7276     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7277     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   7278     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7279     GOTO_OPCODE(ip)                     @ jump to next instruction
   7280 
   7281 
   7282 /* ------------------------------ */
   7283     .balign 64
   7284 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
   7285 /* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
   7286 /* File: armv5te/OP_SPUT_WIDE.S */
   7287     /*
   7288      * 64-bit SPUT handler.
   7289      */
   7290     /* sput-wide vAA, field@BBBB */
   7291     ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
   7292     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7293     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
   7294     mov     r9, rINST, lsr #8           @ r9<- AA
   7295     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
   7296     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   7297     cmp     r2, #0                      @ is resolved entry null?
   7298     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
   7299 .LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
   7300     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7301     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   7302     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   7303     .if 1
   7304     add     r2, r2, #offStaticField_value @ r2<- pointer to data
   7305     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   7306     .else
   7307     strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
   7308     .endif
   7309     GOTO_OPCODE(r10)                    @ jump to next instruction
   7310 
   7311 
   7312 /* ------------------------------ */
   7313     .balign 64
   7314 .L_OP_BREAKPOINT: /* 0xec */
   7315 /* File: armv5te/OP_BREAKPOINT.S */
   7316 /* File: armv5te/unused.S */
   7317     bl      common_abort
   7318 
   7319 
   7320 /* ------------------------------ */
   7321     .balign 64
   7322 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
   7323 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
   7324     /*
   7325      * Handle a throw-verification-error instruction.  This throws an
   7326      * exception for an error discovered during verification.  The
   7327      * exception is indicated by AA, with some detail provided by BBBB.
   7328      */
   7329     /* op AA, ref@BBBB */
   7330     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
   7331     FETCH(r2, 1)                        @ r2<- BBBB
   7332     EXPORT_PC()                         @ export the PC
   7333     mov     r1, rINST, lsr #8           @ r1<- AA
   7334     bl      dvmThrowVerificationError   @ always throws
   7335     b       common_exceptionThrown      @ handle exception
   7336 
   7337 /* ------------------------------ */
   7338     .balign 64
   7339 .L_OP_EXECUTE_INLINE: /* 0xee */
   7340 /* File: armv5te/OP_EXECUTE_INLINE.S */
   7341     /*
   7342      * Execute a "native inline" instruction.
   7343      *
   7344      * We need to call an InlineOp4Func:
   7345      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
   7346      *
   7347      * The first four args are in r0-r3, pointer to return value storage
   7348      * is on the stack.  The function's return value is a flag that tells
   7349      * us if an exception was thrown.
   7350      */
   7351     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
   7352     FETCH(r10, 1)                       @ r10<- BBBB
   7353     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
   7354     EXPORT_PC()                         @ can throw
   7355     sub     sp, sp, #8                  @ make room for arg, +64 bit align
   7356     mov     r0, rINST, lsr #12          @ r0<- B
   7357     str     r1, [sp]                    @ push &glue->retval
   7358     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
   7359     add     sp, sp, #8                  @ pop stack
   7360     cmp     r0, #0                      @ test boolean result of inline
   7361     beq     common_exceptionThrown      @ returned false, handle exception
   7362     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7363     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7364     GOTO_OPCODE(ip)                     @ jump to next instruction
   7365 
   7366 /* ------------------------------ */
   7367     .balign 64
   7368 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
   7369 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
   7370     /*
   7371      * Execute a "native inline" instruction, using "/range" semantics.
   7372      * Same idea as execute-inline, but we get the args differently.
   7373      *
   7374      * We need to call an InlineOp4Func:
   7375      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
   7376      *
   7377      * The first four args are in r0-r3, pointer to return value storage
   7378      * is on the stack.  The function's return value is a flag that tells
   7379      * us if an exception was thrown.
   7380      */
   7381     /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
   7382     FETCH(r10, 1)                       @ r10<- BBBB
   7383     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
   7384     EXPORT_PC()                         @ can throw
   7385     sub     sp, sp, #8                  @ make room for arg, +64 bit align
   7386     mov     r0, rINST, lsr #8           @ r0<- AA
   7387     str     r1, [sp]                    @ push &glue->retval
   7388     bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
   7389     add     sp, sp, #8                  @ pop stack
   7390     cmp     r0, #0                      @ test boolean result of inline
   7391     beq     common_exceptionThrown      @ returned false, handle exception
   7392     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7393     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7394     GOTO_OPCODE(ip)                     @ jump to next instruction
   7395 
   7396 /* ------------------------------ */
   7397     .balign 64
   7398 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
   7399 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
   7400     /*
   7401      * invoke-direct-empty is a no-op in a "standard" interpreter.
   7402      */
   7403     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   7404     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
   7405     GOTO_OPCODE(ip)                     @ execute it
   7406 
   7407 /* ------------------------------ */
   7408     .balign 64
   7409 .L_OP_UNUSED_F1: /* 0xf1 */
   7410 /* File: armv5te/OP_UNUSED_F1.S */
   7411 /* File: armv5te/unused.S */
   7412     bl      common_abort
   7413 
   7414 
   7415 /* ------------------------------ */
   7416     .balign 64
   7417 .L_OP_IGET_QUICK: /* 0xf2 */
   7418 /* File: armv6t2/OP_IGET_QUICK.S */
   7419     /* For: iget-quick, iget-object-quick */
   7420     /* op vA, vB, offset@CCCC */
   7421     mov     r2, rINST, lsr #12          @ r2<- B
   7422     FETCH(r1, 1)                        @ r1<- field byte offset
   7423     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7424     ubfx    r2, rINST, #8, #4           @ r2<- A
   7425     cmp     r3, #0                      @ check object for null
   7426     beq     common_errNullObject        @ object was null
   7427     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
   7428     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7429     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7430     SET_VREG(r0, r2)                    @ fp[A]<- r0
   7431     GOTO_OPCODE(ip)                     @ jump to next instruction
   7432 
   7433 /* ------------------------------ */
   7434     .balign 64
   7435 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
   7436 /* File: armv6t2/OP_IGET_WIDE_QUICK.S */
   7437     /* iget-wide-quick vA, vB, offset@CCCC */
   7438     mov     r2, rINST, lsr #12          @ r2<- B
   7439     FETCH(ip, 1)                        @ ip<- field byte offset
   7440     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7441     ubfx    r2, rINST, #8, #4           @ r2<- A
   7442     cmp     r3, #0                      @ check object for null
   7443     beq     common_errNullObject        @ object was null
   7444     ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
   7445     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7446     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   7447     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7448     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   7449     GOTO_OPCODE(ip)                     @ jump to next instruction
   7450 
   7451 /* ------------------------------ */
   7452     .balign 64
   7453 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
   7454 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
   7455 /* File: armv5te/OP_IGET_QUICK.S */
   7456     /* For: iget-quick, iget-object-quick */
   7457     /* op vA, vB, offset@CCCC */
   7458     mov     r2, rINST, lsr #12          @ r2<- B
   7459     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7460     FETCH(r1, 1)                        @ r1<- field byte offset
   7461     cmp     r3, #0                      @ check object for null
   7462     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7463     beq     common_errNullObject        @ object was null
   7464     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
   7465     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7466     and     r2, r2, #15
   7467     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7468     SET_VREG(r0, r2)                    @ fp[A]<- r0
   7469     GOTO_OPCODE(ip)                     @ jump to next instruction
   7470 
   7471 
   7472 /* ------------------------------ */
   7473     .balign 64
   7474 .L_OP_IPUT_QUICK: /* 0xf5 */
   7475 /* File: armv6t2/OP_IPUT_QUICK.S */
   7476     /* For: iput-quick, iput-object-quick */
   7477     /* op vA, vB, offset@CCCC */
   7478     mov     r2, rINST, lsr #12          @ r2<- B
   7479     FETCH(r1, 1)                        @ r1<- field byte offset
   7480     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
   7481     ubfx    r2, rINST, #8, #4           @ r2<- A
   7482     cmp     r3, #0                      @ check object for null
   7483     beq     common_errNullObject        @ object was null
   7484     GET_VREG(r0, r2)                    @ r0<- fp[A]
   7485     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7486     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
   7487     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7488     GOTO_OPCODE(ip)                     @ jump to next instruction
   7489 
   7490 /* ------------------------------ */
   7491     .balign 64
   7492 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
   7493 /* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
   7494     /* iput-wide-quick vA, vB, offset@CCCC */
   7495     mov     r1, rINST, lsr #12          @ r1<- B
   7496     ubfx    r0, rINST, #8, #4           @ r0<- A
   7497     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
   7498     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
   7499     cmp     r2, #0                      @ check object for null
   7500     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
   7501     beq     common_errNullObject        @ object was null
   7502     FETCH(r3, 1)                        @ r3<- field byte offset
   7503     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7504     strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
   7505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7506     GOTO_OPCODE(ip)                     @ jump to next instruction
   7507 
   7508 /* ------------------------------ */
   7509     .balign 64
   7510 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
   7511 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
   7512     /* For: iput-object-quick */
   7513     /* op vA, vB, offset@CCCC */
   7514     mov     r2, rINST, lsr #12          @ r2<- B
   7515     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
   7516     FETCH(r1, 1)                        @ r1<- field byte offset
   7517     cmp     r3, #0                      @ check object for null
   7518     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7519     beq     common_errNullObject        @ object was null
   7520     and     r2, r2, #15
   7521     GET_VREG(r0, r2)                    @ r0<- fp[A]
   7522     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   7523     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7524     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
   7525     cmp     r0, #0
   7526     strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
   7527     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7528     GOTO_OPCODE(ip)                     @ jump to next instruction
   7529 
   7530 /* ------------------------------ */
   7531     .balign 64
   7532 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
   7533 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
   7534     /*
   7535      * Handle an optimized virtual method call.
   7536      *
   7537      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
   7538      */
   7539     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7540     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7541     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
   7542     FETCH(r1, 1)                        @ r1<- BBBB
   7543     .if     (!0)
   7544     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
   7545     .endif
   7546     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
   7547     cmp     r2, #0                      @ is "this" null?
   7548     beq     common_errNullObject        @ null "this", throw exception
   7549     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
   7550     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
   7551     EXPORT_PC()                         @ invoke must export
   7552     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
   7553     bl      common_invokeMethodNoRange @ continue on
   7554 
   7555 /* ------------------------------ */
   7556     .balign 64
   7557 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
   7558 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
   7559 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
   7560     /*
   7561      * Handle an optimized virtual method call.
   7562      *
   7563      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
   7564      */
   7565     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7566     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7567     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
   7568     FETCH(r1, 1)                        @ r1<- BBBB
   7569     .if     (!1)
   7570     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
   7571     .endif
   7572     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
   7573     cmp     r2, #0                      @ is "this" null?
   7574     beq     common_errNullObject        @ null "this", throw exception
   7575     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
   7576     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
   7577     EXPORT_PC()                         @ invoke must export
   7578     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
   7579     bl      common_invokeMethodRange @ continue on
   7580 
   7581 
   7582 /* ------------------------------ */
   7583     .balign 64
   7584 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
   7585 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
   7586     /*
   7587      * Handle an optimized "super" method call.
   7588      *
   7589      * for: [opt] invoke-super-quick, invoke-super-quick/range
   7590      */
   7591     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7592     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7593     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   7594     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7595     .if     (!0)
   7596     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   7597     .endif
   7598     FETCH(r1, 1)                        @ r1<- BBBB
   7599     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
   7600     EXPORT_PC()                         @ must export for invoke
   7601     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
   7602     GET_VREG(r3, r10)                   @ r3<- "this"
   7603     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
   7604     cmp     r3, #0                      @ null "this" ref?
   7605     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
   7606     beq     common_errNullObject        @ "this" is null, throw exception
   7607     bl      common_invokeMethodNoRange @ continue on
   7608 
   7609 /* ------------------------------ */
   7610     .balign 64
   7611 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
   7612 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
   7613 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
   7614     /*
   7615      * Handle an optimized "super" method call.
   7616      *
   7617      * for: [opt] invoke-super-quick, invoke-super-quick/range
   7618      */
   7619     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7620     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7621     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   7622     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7623     .if     (!1)
   7624     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   7625     .endif
   7626     FETCH(r1, 1)                        @ r1<- BBBB
   7627     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
   7628     EXPORT_PC()                         @ must export for invoke
   7629     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
   7630     GET_VREG(r3, r10)                   @ r3<- "this"
   7631     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
   7632     cmp     r3, #0                      @ null "this" ref?
   7633     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
   7634     beq     common_errNullObject        @ "this" is null, throw exception
   7635     bl      common_invokeMethodRange @ continue on
   7636 
   7637 
   7638 /* ------------------------------ */
   7639     .balign 64
   7640 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
   7641 /* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
   7642 /* File: armv5te/OP_IPUT_OBJECT.S */
   7643     /*
   7644      * 32-bit instance field put.
   7645      *
   7646      * for: iput-object, iput-object-volatile
   7647      */
   7648     /* op vA, vB, field@CCCC */
   7649     mov     r0, rINST, lsr #12          @ r0<- B
   7650     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7651     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7652     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7653     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7654     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7655     cmp     r0, #0                      @ is resolved entry null?
   7656     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
   7657 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7658     EXPORT_PC()                         @ resolve() could throw
   7659     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7660     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7661     cmp     r0, #0                      @ success?
   7662     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
   7663     b       common_exceptionThrown
   7664 
   7665 
   7666 /* ------------------------------ */
   7667     .balign 64
   7668 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
   7669 /* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
   7670 /* File: armv5te/OP_SGET.S */
   7671     /*
   7672      * General 32-bit SGET handler.
   7673      *
   7674      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   7675      */
   7676     /* op vAA, field@BBBB */
   7677     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7678     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7679     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7680     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7681     cmp     r0, #0                      @ is resolved entry null?
   7682     beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
   7683 .LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
   7684     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   7685     SMP_DMB                            @ acquiring load
   7686     mov     r2, rINST, lsr #8           @ r2<- AA
   7687     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7688     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   7689     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7690     GOTO_OPCODE(ip)                     @ jump to next instruction
   7691 
   7692 
   7693 /* ------------------------------ */
   7694     .balign 64
   7695 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
   7696 /* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
   7697 /* File: armv5te/OP_SPUT_OBJECT.S */
   7698     /*
   7699      * 32-bit SPUT handler for objects
   7700      *
   7701      * for: sput-object, sput-object-volatile
   7702      */
   7703     /* op vAA, field@BBBB */
   7704     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7705     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7706     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7707     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7708     cmp     r0, #0                      @ is resolved entry null?
   7709     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
   7710     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
   7711     EXPORT_PC()                         @ resolve() could throw, so export now
   7712     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
   7713     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   7714     cmp     r0, #0                      @ success?
   7715     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
   7716     b       common_exceptionThrown      @ no, handle exception
   7717 
   7718 
   7719 
   7720 /* ------------------------------ */
   7721     .balign 64
   7722 .L_OP_UNUSED_FF: /* 0xff */
   7723 /* File: armv5te/OP_UNUSED_FF.S */
   7724 /* File: armv5te/unused.S */
   7725     bl      common_abort
   7726 
   7727 
   7728 
   7729     .balign 64
   7730     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
   7731     .global dvmAsmInstructionEnd
   7732 dvmAsmInstructionEnd:
   7733 
   7734 /*
   7735  * ===========================================================================
   7736  *  Sister implementations
   7737  * ===========================================================================
   7738  */
   7739     .global dvmAsmSisterStart
   7740     .type   dvmAsmSisterStart, %function
   7741     .text
   7742     .balign 4
   7743 dvmAsmSisterStart:
   7744 
   7745 /* continuation for OP_CONST_STRING */
   7746 
   7747     /*
   7748      * Continuation if the String has not yet been resolved.
   7749      *  r1: BBBB (String ref)
   7750      *  r9: target register
   7751      */
   7752 .LOP_CONST_STRING_resolve:
   7753     EXPORT_PC()
   7754     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   7755     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7756     bl      dvmResolveString            @ r0<- String reference
   7757     cmp     r0, #0                      @ failed?
   7758     beq     common_exceptionThrown      @ yup, handle the exception
   7759     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7760     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7761     SET_VREG(r0, r9)                    @ vAA<- r0
   7762     GOTO_OPCODE(ip)                     @ jump to next instruction
   7763 
   7764 /* continuation for OP_CONST_STRING_JUMBO */
   7765 
   7766     /*
   7767      * Continuation if the String has not yet been resolved.
   7768      *  r1: BBBBBBBB (String ref)
   7769      *  r9: target register
   7770      */
   7771 .LOP_CONST_STRING_JUMBO_resolve:
   7772     EXPORT_PC()
   7773     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   7774     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7775     bl      dvmResolveString            @ r0<- String reference
   7776     cmp     r0, #0                      @ failed?
   7777     beq     common_exceptionThrown      @ yup, handle the exception
   7778     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7779     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7780     SET_VREG(r0, r9)                    @ vAA<- r0
   7781     GOTO_OPCODE(ip)                     @ jump to next instruction
   7782 
   7783 /* continuation for OP_CONST_CLASS */
   7784 
   7785     /*
   7786      * Continuation if the Class has not yet been resolved.
   7787      *  r1: BBBB (Class ref)
   7788      *  r9: target register
   7789      */
   7790 .LOP_CONST_CLASS_resolve:
   7791     EXPORT_PC()
   7792     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   7793     mov     r2, #1                      @ r2<- true
   7794     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7795     bl      dvmResolveClass             @ r0<- Class reference
   7796     cmp     r0, #0                      @ failed?
   7797     beq     common_exceptionThrown      @ yup, handle the exception
   7798     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7799     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7800     SET_VREG(r0, r9)                    @ vAA<- r0
   7801     GOTO_OPCODE(ip)                     @ jump to next instruction
   7802 
   7803 /* continuation for OP_CHECK_CAST */
   7804 
   7805     /*
   7806      * Trivial test failed, need to perform full check.  This is common.
   7807      *  r0 holds obj->clazz
   7808      *  r1 holds class resolved from BBBB
   7809      *  r9 holds object
   7810      */
   7811 .LOP_CHECK_CAST_fullcheck:
   7812     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
   7813     cmp     r0, #0                      @ failed?
   7814     bne     .LOP_CHECK_CAST_okay            @ no, success
   7815 
   7816     @ A cast has failed.  We need to throw a ClassCastException with the
   7817     @ class of the object that failed to be cast.
   7818     EXPORT_PC()                         @ about to throw
   7819     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
   7820     ldr     r0, .LstrClassCastExceptionPtr
   7821     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
   7822     bl      dvmThrowExceptionWithClassMessage
   7823     b       common_exceptionThrown
   7824 
   7825     /*
   7826      * Resolution required.  This is the least-likely path.
   7827      *
   7828      *  r2 holds BBBB
   7829      *  r9 holds object
   7830      */
   7831 .LOP_CHECK_CAST_resolve:
   7832     EXPORT_PC()                         @ resolve() could throw
   7833     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   7834     mov     r1, r2                      @ r1<- BBBB
   7835     mov     r2, #0                      @ r2<- false
   7836     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   7837     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   7838     cmp     r0, #0                      @ got null?
   7839     beq     common_exceptionThrown      @ yes, handle exception
   7840     mov     r1, r0                      @ r1<- class resolved from BBB
   7841     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
   7842     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
   7843 
   7844 .LstrClassCastExceptionPtr:
   7845     .word   .LstrClassCastException
   7846 
   7847 /* continuation for OP_INSTANCE_OF */
   7848 
   7849     /*
   7850      * Trivial test failed, need to perform full check.  This is common.
   7851      *  r0 holds obj->clazz
   7852      *  r1 holds class resolved from BBBB
   7853      *  r9 holds A
   7854      */
   7855 .LOP_INSTANCE_OF_fullcheck:
   7856     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
   7857     @ fall through to OP_INSTANCE_OF_store
   7858 
   7859     /*
   7860      * r0 holds boolean result
   7861      * r9 holds A
   7862      */
   7863 .LOP_INSTANCE_OF_store:
   7864     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7865     SET_VREG(r0, r9)                    @ vA<- r0
   7866     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7867     GOTO_OPCODE(ip)                     @ jump to next instruction
   7868 
   7869     /*
   7870      * Trivial test succeeded, save and bail.
   7871      *  r9 holds A
   7872      */
   7873 .LOP_INSTANCE_OF_trivial:
   7874     mov     r0, #1                      @ indicate success
   7875     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
   7876     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7877     SET_VREG(r0, r9)                    @ vA<- r0
   7878     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7879     GOTO_OPCODE(ip)                     @ jump to next instruction
   7880 
   7881     /*
   7882      * Resolution required.  This is the least-likely path.
   7883      *
   7884      *  r3 holds BBBB
   7885      *  r9 holds A
   7886      */
   7887 .LOP_INSTANCE_OF_resolve:
   7888     EXPORT_PC()                         @ resolve() could throw
   7889     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
   7890     mov     r1, r3                      @ r1<- BBBB
   7891     mov     r2, #1                      @ r2<- true
   7892     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7893     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   7894     cmp     r0, #0                      @ got null?
   7895     beq     common_exceptionThrown      @ yes, handle exception
   7896     mov     r1, r0                      @ r1<- class resolved from BBB
   7897     mov     r3, rINST, lsr #12          @ r3<- B
   7898     GET_VREG(r0, r3)                    @ r0<- vB (object)
   7899     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
   7900     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
   7901 
   7902 /* continuation for OP_NEW_INSTANCE */
   7903 
   7904     .balign 32                          @ minimize cache lines
   7905 .LOP_NEW_INSTANCE_finish: @ r0=new object
   7906     mov     r3, rINST, lsr #8           @ r3<- AA
   7907     cmp     r0, #0                      @ failed?
   7908     beq     common_exceptionThrown      @ yes, handle the exception
   7909     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7910     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7911     SET_VREG(r0, r3)                    @ vAA<- r0
   7912     GOTO_OPCODE(ip)                     @ jump to next instruction
   7913 
   7914     /*
   7915      * Class initialization required.
   7916      *
   7917      *  r0 holds class object
   7918      */
   7919 .LOP_NEW_INSTANCE_needinit:
   7920     mov     r9, r0                      @ save r0
   7921     bl      dvmInitClass                @ initialize class
   7922     cmp     r0, #0                      @ check boolean result
   7923     mov     r0, r9                      @ restore r0
   7924     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
   7925     b       common_exceptionThrown      @ failed, deal with init exception
   7926 
   7927     /*
   7928      * Resolution required.  This is the least-likely path.
   7929      *
   7930      *  r1 holds BBBB
   7931      */
   7932 .LOP_NEW_INSTANCE_resolve:
   7933     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   7934     mov     r2, #0                      @ r2<- false
   7935     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   7936     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   7937     cmp     r0, #0                      @ got null?
   7938     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
   7939     b       common_exceptionThrown      @ yes, handle exception
   7940 
   7941 .LstrInstantiationErrorPtr:
   7942     .word   .LstrInstantiationError
   7943 
   7944 /* continuation for OP_NEW_ARRAY */
   7945 
   7946 
   7947     /*
   7948      * Resolve class.  (This is an uncommon case.)
   7949      *
   7950      *  r1 holds array length
   7951      *  r2 holds class ref CCCC
   7952      */
   7953 .LOP_NEW_ARRAY_resolve:
   7954     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   7955     mov     r9, r1                      @ r9<- length (save)
   7956     mov     r1, r2                      @ r1<- CCCC
   7957     mov     r2, #0                      @ r2<- false
   7958     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   7959     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   7960     cmp     r0, #0                      @ got null?
   7961     mov     r1, r9                      @ r1<- length (restore)
   7962     beq     common_exceptionThrown      @ yes, handle exception
   7963     @ fall through to OP_NEW_ARRAY_finish
   7964 
   7965     /*
   7966      * Finish allocation.
   7967      *
   7968      *  r0 holds class
   7969      *  r1 holds array length
   7970      */
   7971 .LOP_NEW_ARRAY_finish:
   7972     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
   7973     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
   7974     cmp     r0, #0                      @ failed?
   7975     mov     r2, rINST, lsr #8           @ r2<- A+
   7976     beq     common_exceptionThrown      @ yes, handle the exception
   7977     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7978     and     r2, r2, #15                 @ r2<- A
   7979     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7980     SET_VREG(r0, r2)                    @ vA<- r0
   7981     GOTO_OPCODE(ip)                     @ jump to next instruction
   7982 
   7983 /* continuation for OP_FILLED_NEW_ARRAY */
   7984 
   7985     /*
   7986      * On entry:
   7987      *  r0 holds array class
   7988      *  r10 holds AA or BA
   7989      */
   7990 .LOP_FILLED_NEW_ARRAY_continue:
   7991     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
   7992     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
   7993     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
   7994     .if     0
   7995     mov     r1, r10                     @ r1<- AA (length)
   7996     .else
   7997     mov     r1, r10, lsr #4             @ r1<- B (length)
   7998     .endif
   7999     cmp     rINST, #'I'                 @ array of ints?
   8000     cmpne   rINST, #'L'                 @ array of objects?
   8001     cmpne   rINST, #'['                 @ array of arrays?
   8002     mov     r9, r1                      @ save length in r9
   8003     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
   8004     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
   8005     cmp     r0, #0                      @ null return?
   8006     beq     common_exceptionThrown      @ alloc failed, handle exception
   8007 
   8008     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
   8009     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
   8010     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
   8011     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
   8012     subs    r9, r9, #1                  @ length--, check for neg
   8013     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   8014     bmi     2f                          @ was zero, bail
   8015 
   8016     @ copy values from registers into the array
   8017     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
   8018     .if     0
   8019     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
   8020 1:  ldr     r3, [r2], #4                @ r3<- *r2++
   8021     subs    r9, r9, #1                  @ count--
   8022     str     r3, [r0], #4                @ *contents++ = vX
   8023     bpl     1b
   8024     @ continue at 2
   8025     .else
   8026     cmp     r9, #4                      @ length was initially 5?
   8027     and     r2, r10, #15                @ r2<- A
   8028     bne     1f                          @ <= 4 args, branch
   8029     GET_VREG(r3, r2)                    @ r3<- vA
   8030     sub     r9, r9, #1                  @ count--
   8031     str     r3, [r0, #16]               @ contents[4] = vA
   8032 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
   8033     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
   8034     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
   8035     subs    r9, r9, #1                  @ count--
   8036     str     r3, [r0], #4                @ *contents++ = vX
   8037     bpl     1b
   8038     @ continue at 2
   8039     .endif
   8040 
   8041 2:
   8042     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
   8043     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
   8044     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8045     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
   8046     cmp     r1, #'I'                         @ Is int array?
   8047     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
   8048     GOTO_OPCODE(ip)                          @ execute it
   8049 
   8050     /*
   8051      * Throw an exception indicating that we have not implemented this
   8052      * mode of filled-new-array.
   8053      */
   8054 .LOP_FILLED_NEW_ARRAY_notimpl:
   8055     ldr     r0, .L_strInternalError
   8056     ldr     r1, .L_strFilledNewArrayNotImpl
   8057     bl      dvmThrowException
   8058     b       common_exceptionThrown
   8059 
   8060     .if     (!0)                 @ define in one or the other, not both
   8061 .L_strFilledNewArrayNotImpl:
   8062     .word   .LstrFilledNewArrayNotImpl
   8063 .L_strInternalError:
   8064     .word   .LstrInternalError
   8065     .endif
   8066 
   8067 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
   8068 
   8069     /*
   8070      * On entry:
   8071      *  r0 holds array class
   8072      *  r10 holds AA or BA
   8073      */
   8074 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
   8075     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
   8076     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
   8077     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
   8078     .if     1
   8079     mov     r1, r10                     @ r1<- AA (length)
   8080     .else
   8081     mov     r1, r10, lsr #4             @ r1<- B (length)
   8082     .endif
   8083     cmp     rINST, #'I'                 @ array of ints?
   8084     cmpne   rINST, #'L'                 @ array of objects?
   8085     cmpne   rINST, #'['                 @ array of arrays?
   8086     mov     r9, r1                      @ save length in r9
   8087     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
   8088     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
   8089     cmp     r0, #0                      @ null return?
   8090     beq     common_exceptionThrown      @ alloc failed, handle exception
   8091 
   8092     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
   8093     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
   8094     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
   8095     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
   8096     subs    r9, r9, #1                  @ length--, check for neg
   8097     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   8098     bmi     2f                          @ was zero, bail
   8099 
   8100     @ copy values from registers into the array
   8101     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
   8102     .if     1
   8103     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
   8104 1:  ldr     r3, [r2], #4                @ r3<- *r2++
   8105     subs    r9, r9, #1                  @ count--
   8106     str     r3, [r0], #4                @ *contents++ = vX
   8107     bpl     1b
   8108     @ continue at 2
   8109     .else
   8110     cmp     r9, #4                      @ length was initially 5?
   8111     and     r2, r10, #15                @ r2<- A
   8112     bne     1f                          @ <= 4 args, branch
   8113     GET_VREG(r3, r2)                    @ r3<- vA
   8114     sub     r9, r9, #1                  @ count--
   8115     str     r3, [r0, #16]               @ contents[4] = vA
   8116 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
   8117     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
   8118     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
   8119     subs    r9, r9, #1                  @ count--
   8120     str     r3, [r0], #4                @ *contents++ = vX
   8121     bpl     1b
   8122     @ continue at 2
   8123     .endif
   8124 
   8125 2:
   8126     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
   8127     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
   8128     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8129     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
   8130     cmp     r1, #'I'                         @ Is int array?
   8131     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
   8132     GOTO_OPCODE(ip)                          @ execute it
   8133 
   8134     /*
   8135      * Throw an exception indicating that we have not implemented this
   8136      * mode of filled-new-array.
   8137      */
   8138 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
   8139     ldr     r0, .L_strInternalError
   8140     ldr     r1, .L_strFilledNewArrayNotImpl
   8141     bl      dvmThrowException
   8142     b       common_exceptionThrown
   8143 
   8144     .if     (!1)                 @ define in one or the other, not both
   8145 .L_strFilledNewArrayNotImpl:
   8146     .word   .LstrFilledNewArrayNotImpl
   8147 .L_strInternalError:
   8148     .word   .LstrInternalError
   8149     .endif
   8150 
   8151 /* continuation for OP_CMPL_FLOAT */
   8152 .LOP_CMPL_FLOAT_finish:
   8153     SET_VREG(r0, r9)                    @ vAA<- r0
   8154     GOTO_OPCODE(ip)                     @ jump to next instruction
   8155 
   8156 /* continuation for OP_CMPG_FLOAT */
   8157 .LOP_CMPG_FLOAT_finish:
   8158     SET_VREG(r0, r9)                    @ vAA<- r0
   8159     GOTO_OPCODE(ip)                     @ jump to next instruction
   8160 
   8161 /* continuation for OP_CMPL_DOUBLE */
   8162 .LOP_CMPL_DOUBLE_finish:
   8163     SET_VREG(r0, r9)                    @ vAA<- r0
   8164     GOTO_OPCODE(ip)                     @ jump to next instruction
   8165 
   8166 /* continuation for OP_CMPG_DOUBLE */
   8167 .LOP_CMPG_DOUBLE_finish:
   8168     SET_VREG(r0, r9)                    @ vAA<- r0
   8169     GOTO_OPCODE(ip)                     @ jump to next instruction
   8170 
   8171 /* continuation for OP_CMP_LONG */
   8172 
   8173 .LOP_CMP_LONG_less:
   8174     mvn     r1, #0                      @ r1<- -1
   8175     @ Want to cond code the next mov so we can avoid branch, but don't see it;
   8176     @ instead, we just replicate the tail end.
   8177     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8178     SET_VREG(r1, r9)                    @ vAA<- r1
   8179     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8180     GOTO_OPCODE(ip)                     @ jump to next instruction
   8181 
   8182 .LOP_CMP_LONG_greater:
   8183     mov     r1, #1                      @ r1<- 1
   8184     @ fall through to _finish
   8185 
   8186 .LOP_CMP_LONG_finish:
   8187     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8188     SET_VREG(r1, r9)                    @ vAA<- r1
   8189     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8190     GOTO_OPCODE(ip)                     @ jump to next instruction
   8191 
   8192 /* continuation for OP_AGET_WIDE */
   8193 
   8194 .LOP_AGET_WIDE_finish:
   8195     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8196     ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
   8197     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   8198     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8199     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
   8200     GOTO_OPCODE(ip)                     @ jump to next instruction
   8201 
   8202 /* continuation for OP_APUT_WIDE */
   8203 
   8204 .LOP_APUT_WIDE_finish:
   8205     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8206     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
   8207     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8208     strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
   8209     GOTO_OPCODE(ip)                     @ jump to next instruction
   8210 
   8211 /* continuation for OP_APUT_OBJECT */
   8212     /*
   8213      * On entry:
   8214      *  rINST = vBB (arrayObj)
   8215      *  r9 = vAA (obj)
   8216      *  r10 = offset into array (vBB + vCC * width)
   8217      */
   8218 .LOP_APUT_OBJECT_finish:
   8219     cmp     r9, #0                      @ storing null reference?
   8220     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
   8221     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
   8222     ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
   8223     bl      dvmCanPutArrayElement       @ test object type vs. array type
   8224     cmp     r0, #0                      @ okay?
   8225     beq     common_errArrayStore        @ no
   8226     mov     r1, rINST                   @ r1<- arrayObj
   8227     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8228     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
   8229     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
   8230     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8231     str     r9, [r10]                   @ vBB[vCC]<- vAA
   8232     strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
   8233     GOTO_OPCODE(ip)                     @ jump to next instruction
   8234 .LOP_APUT_OBJECT_skip_check:
   8235     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8236     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8237     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
   8238     GOTO_OPCODE(ip)                     @ jump to next instruction
   8239 
   8240 /* continuation for OP_IGET */
   8241 
   8242     /*
   8243      * Currently:
   8244      *  r0 holds resolved field
   8245      *  r9 holds object
   8246      */
   8247 .LOP_IGET_finish:
   8248     @bl      common_squeak0
   8249     cmp     r9, #0                      @ check object for null
   8250     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8251     beq     common_errNullObject        @ object was null
   8252     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8253     ubfx    r2, rINST, #8, #4           @ r2<- A
   8254     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8255     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8256     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8257     GOTO_OPCODE(ip)                     @ jump to next instruction
   8258 
   8259 /* continuation for OP_IGET_WIDE */
   8260 
   8261     /*
   8262      * Currently:
   8263      *  r0 holds resolved field
   8264      *  r9 holds object
   8265      */
   8266 .LOP_IGET_WIDE_finish:
   8267     cmp     r9, #0                      @ check object for null
   8268     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8269     beq     common_errNullObject        @ object was null
   8270     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
   8271     ubfx    r2, rINST, #8, #4           @ r2<- A
   8272     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8273     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   8274     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8275     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   8276     GOTO_OPCODE(ip)                     @ jump to next instruction
   8277 
   8278 /* continuation for OP_IGET_OBJECT */
   8279 
   8280     /*
   8281      * Currently:
   8282      *  r0 holds resolved field
   8283      *  r9 holds object
   8284      */
   8285 .LOP_IGET_OBJECT_finish:
   8286     @bl      common_squeak0
   8287     cmp     r9, #0                      @ check object for null
   8288     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8289     beq     common_errNullObject        @ object was null
   8290     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8291     @ no-op                             @ acquiring load
   8292     mov     r2, rINST, lsr #8           @ r2<- A+
   8293     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8294     and     r2, r2, #15                 @ r2<- A
   8295     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8296     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8297     GOTO_OPCODE(ip)                     @ jump to next instruction
   8298 
   8299 /* continuation for OP_IGET_BOOLEAN */
   8300 
   8301     /*
   8302      * Currently:
   8303      *  r0 holds resolved field
   8304      *  r9 holds object
   8305      */
   8306 .LOP_IGET_BOOLEAN_finish:
   8307     @bl      common_squeak1
   8308     cmp     r9, #0                      @ check object for null
   8309     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8310     beq     common_errNullObject        @ object was null
   8311     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8312     @ no-op                             @ acquiring load
   8313     mov     r2, rINST, lsr #8           @ r2<- A+
   8314     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8315     and     r2, r2, #15                 @ r2<- A
   8316     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8317     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8318     GOTO_OPCODE(ip)                     @ jump to next instruction
   8319 
   8320 /* continuation for OP_IGET_BYTE */
   8321 
   8322     /*
   8323      * Currently:
   8324      *  r0 holds resolved field
   8325      *  r9 holds object
   8326      */
   8327 .LOP_IGET_BYTE_finish:
   8328     @bl      common_squeak2
   8329     cmp     r9, #0                      @ check object for null
   8330     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8331     beq     common_errNullObject        @ object was null
   8332     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8333     @ no-op                             @ acquiring load
   8334     mov     r2, rINST, lsr #8           @ r2<- A+
   8335     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8336     and     r2, r2, #15                 @ r2<- A
   8337     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8338     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8339     GOTO_OPCODE(ip)                     @ jump to next instruction
   8340 
   8341 /* continuation for OP_IGET_CHAR */
   8342 
   8343     /*
   8344      * Currently:
   8345      *  r0 holds resolved field
   8346      *  r9 holds object
   8347      */
   8348 .LOP_IGET_CHAR_finish:
   8349     @bl      common_squeak3
   8350     cmp     r9, #0                      @ check object for null
   8351     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8352     beq     common_errNullObject        @ object was null
   8353     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8354     @ no-op                             @ acquiring load
   8355     mov     r2, rINST, lsr #8           @ r2<- A+
   8356     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8357     and     r2, r2, #15                 @ r2<- A
   8358     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8359     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8360     GOTO_OPCODE(ip)                     @ jump to next instruction
   8361 
   8362 /* continuation for OP_IGET_SHORT */
   8363 
   8364     /*
   8365      * Currently:
   8366      *  r0 holds resolved field
   8367      *  r9 holds object
   8368      */
   8369 .LOP_IGET_SHORT_finish:
   8370     @bl      common_squeak4
   8371     cmp     r9, #0                      @ check object for null
   8372     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8373     beq     common_errNullObject        @ object was null
   8374     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8375     @ no-op                             @ acquiring load
   8376     mov     r2, rINST, lsr #8           @ r2<- A+
   8377     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8378     and     r2, r2, #15                 @ r2<- A
   8379     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8380     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8381     GOTO_OPCODE(ip)                     @ jump to next instruction
   8382 
   8383 /* continuation for OP_IPUT */
   8384 
   8385     /*
   8386      * Currently:
   8387      *  r0 holds resolved field
   8388      *  r9 holds object
   8389      */
   8390 .LOP_IPUT_finish:
   8391     @bl      common_squeak0
   8392     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8393     ubfx    r1, rINST, #8, #4           @ r1<- A
   8394     cmp     r9, #0                      @ check object for null
   8395     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8396     beq     common_errNullObject        @ object was null
   8397     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8398     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8399     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8400     GOTO_OPCODE(ip)                     @ jump to next instruction
   8401 
   8402 /* continuation for OP_IPUT_WIDE */
   8403 
   8404     /*
   8405      * Currently:
   8406      *  r0 holds resolved field
   8407      *  r9 holds object
   8408      */
   8409 .LOP_IPUT_WIDE_finish:
   8410     ubfx    r2, rINST, #8, #4           @ r2<- A
   8411     cmp     r9, #0                      @ check object for null
   8412     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8413     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
   8414     beq     common_errNullObject        @ object was null
   8415     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8416     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
   8417     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8418     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
   8419     GOTO_OPCODE(ip)                     @ jump to next instruction
   8420 
   8421 /* continuation for OP_IPUT_OBJECT */
   8422 
   8423     /*
   8424      * Currently:
   8425      *  r0 holds resolved field
   8426      *  r9 holds object
   8427      */
   8428 .LOP_IPUT_OBJECT_finish:
   8429     @bl      common_squeak0
   8430     mov     r1, rINST, lsr #8           @ r1<- A+
   8431     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8432     and     r1, r1, #15                 @ r1<- A
   8433     cmp     r9, #0                      @ check object for null
   8434     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8435     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8436     beq     common_errNullObject        @ object was null
   8437     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8438     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8439     @ no-op                             @ releasing store
   8440     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
   8441     cmp     r0, #0                      @ stored a null reference?
   8442     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
   8443     GOTO_OPCODE(ip)                     @ jump to next instruction
   8444 
   8445 /* continuation for OP_IPUT_BOOLEAN */
   8446 
   8447     /*
   8448      * Currently:
   8449      *  r0 holds resolved field
   8450      *  r9 holds object
   8451      */
   8452 .LOP_IPUT_BOOLEAN_finish:
   8453     @bl      common_squeak1
   8454     mov     r1, rINST, lsr #8           @ r1<- A+
   8455     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8456     and     r1, r1, #15                 @ r1<- A
   8457     cmp     r9, #0                      @ check object for null
   8458     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8459     beq     common_errNullObject        @ object was null
   8460     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8461     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8462     @ no-op                             @ releasing store
   8463     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8464     GOTO_OPCODE(ip)                     @ jump to next instruction
   8465 
   8466 /* continuation for OP_IPUT_BYTE */
   8467 
   8468     /*
   8469      * Currently:
   8470      *  r0 holds resolved field
   8471      *  r9 holds object
   8472      */
   8473 .LOP_IPUT_BYTE_finish:
   8474     @bl      common_squeak2
   8475     mov     r1, rINST, lsr #8           @ r1<- A+
   8476     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8477     and     r1, r1, #15                 @ r1<- A
   8478     cmp     r9, #0                      @ check object for null
   8479     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8480     beq     common_errNullObject        @ object was null
   8481     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8482     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8483     @ no-op                             @ releasing store
   8484     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8485     GOTO_OPCODE(ip)                     @ jump to next instruction
   8486 
   8487 /* continuation for OP_IPUT_CHAR */
   8488 
   8489     /*
   8490      * Currently:
   8491      *  r0 holds resolved field
   8492      *  r9 holds object
   8493      */
   8494 .LOP_IPUT_CHAR_finish:
   8495     @bl      common_squeak3
   8496     mov     r1, rINST, lsr #8           @ r1<- A+
   8497     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8498     and     r1, r1, #15                 @ r1<- A
   8499     cmp     r9, #0                      @ check object for null
   8500     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8501     beq     common_errNullObject        @ object was null
   8502     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8503     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8504     @ no-op                             @ releasing store
   8505     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8506     GOTO_OPCODE(ip)                     @ jump to next instruction
   8507 
   8508 /* continuation for OP_IPUT_SHORT */
   8509 
   8510     /*
   8511      * Currently:
   8512      *  r0 holds resolved field
   8513      *  r9 holds object
   8514      */
   8515 .LOP_IPUT_SHORT_finish:
   8516     @bl      common_squeak4
   8517     mov     r1, rINST, lsr #8           @ r1<- A+
   8518     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8519     and     r1, r1, #15                 @ r1<- A
   8520     cmp     r9, #0                      @ check object for null
   8521     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8522     beq     common_errNullObject        @ object was null
   8523     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8524     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8525     @ no-op                             @ releasing store
   8526     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8527     GOTO_OPCODE(ip)                     @ jump to next instruction
   8528 
   8529 /* continuation for OP_SGET */
   8530 
   8531     /*
   8532      * Continuation if the field has not yet been resolved.
   8533      *  r1: BBBB field ref
   8534      */
   8535 .LOP_SGET_resolve:
   8536     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8537     EXPORT_PC()                         @ resolve() could throw, so export now
   8538     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8539     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8540     cmp     r0, #0                      @ success?
   8541     bne     .LOP_SGET_finish          @ yes, finish
   8542     b       common_exceptionThrown      @ no, handle exception
   8543 
   8544 /* continuation for OP_SGET_WIDE */
   8545 
   8546     /*
   8547      * Continuation if the field has not yet been resolved.
   8548      *  r1: BBBB field ref
   8549      *
   8550      * Returns StaticField pointer in r0.
   8551      */
   8552 .LOP_SGET_WIDE_resolve:
   8553     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8554     EXPORT_PC()                         @ resolve() could throw, so export now
   8555     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8556     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8557     cmp     r0, #0                      @ success?
   8558     bne     .LOP_SGET_WIDE_finish          @ yes, finish
   8559     b       common_exceptionThrown      @ no, handle exception
   8560 
   8561 /* continuation for OP_SGET_OBJECT */
   8562 
   8563     /*
   8564      * Continuation if the field has not yet been resolved.
   8565      *  r1: BBBB field ref
   8566      */
   8567 .LOP_SGET_OBJECT_resolve:
   8568     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8569     EXPORT_PC()                         @ resolve() could throw, so export now
   8570     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8571     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8572     cmp     r0, #0                      @ success?
   8573     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
   8574     b       common_exceptionThrown      @ no, handle exception
   8575 
   8576 /* continuation for OP_SGET_BOOLEAN */
   8577 
   8578     /*
   8579      * Continuation if the field has not yet been resolved.
   8580      *  r1: BBBB field ref
   8581      */
   8582 .LOP_SGET_BOOLEAN_resolve:
   8583     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8584     EXPORT_PC()                         @ resolve() could throw, so export now
   8585     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8586     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8587     cmp     r0, #0                      @ success?
   8588     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
   8589     b       common_exceptionThrown      @ no, handle exception
   8590 
   8591 /* continuation for OP_SGET_BYTE */
   8592 
   8593     /*
   8594      * Continuation if the field has not yet been resolved.
   8595      *  r1: BBBB field ref
   8596      */
   8597 .LOP_SGET_BYTE_resolve:
   8598     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8599     EXPORT_PC()                         @ resolve() could throw, so export now
   8600     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8601     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8602     cmp     r0, #0                      @ success?
   8603     bne     .LOP_SGET_BYTE_finish          @ yes, finish
   8604     b       common_exceptionThrown      @ no, handle exception
   8605 
   8606 /* continuation for OP_SGET_CHAR */
   8607 
   8608     /*
   8609      * Continuation if the field has not yet been resolved.
   8610      *  r1: BBBB field ref
   8611      */
   8612 .LOP_SGET_CHAR_resolve:
   8613     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8614     EXPORT_PC()                         @ resolve() could throw, so export now
   8615     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8616     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8617     cmp     r0, #0                      @ success?
   8618     bne     .LOP_SGET_CHAR_finish          @ yes, finish
   8619     b       common_exceptionThrown      @ no, handle exception
   8620 
   8621 /* continuation for OP_SGET_SHORT */
   8622 
   8623     /*
   8624      * Continuation if the field has not yet been resolved.
   8625      *  r1: BBBB field ref
   8626      */
   8627 .LOP_SGET_SHORT_resolve:
   8628     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8629     EXPORT_PC()                         @ resolve() could throw, so export now
   8630     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8631     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8632     cmp     r0, #0                      @ success?
   8633     bne     .LOP_SGET_SHORT_finish          @ yes, finish
   8634     b       common_exceptionThrown      @ no, handle exception
   8635 
   8636 /* continuation for OP_SPUT */
   8637 
   8638     /*
   8639      * Continuation if the field has not yet been resolved.
   8640      *  r1: BBBB field ref
   8641      */
   8642 .LOP_SPUT_resolve:
   8643     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8644     EXPORT_PC()                         @ resolve() could throw, so export now
   8645     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8646     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8647     cmp     r0, #0                      @ success?
   8648     bne     .LOP_SPUT_finish          @ yes, finish
   8649     b       common_exceptionThrown      @ no, handle exception
   8650 
   8651 /* continuation for OP_SPUT_WIDE */
   8652 
   8653     /*
   8654      * Continuation if the field has not yet been resolved.
   8655      *  r1: BBBB field ref
   8656      *  r9: &fp[AA]
   8657      *
   8658      * Returns StaticField pointer in r2.
   8659      */
   8660 .LOP_SPUT_WIDE_resolve:
   8661     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8662     EXPORT_PC()                         @ resolve() could throw, so export now
   8663     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8664     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8665     cmp     r0, #0                      @ success?
   8666     mov     r2, r0                      @ copy to r2
   8667     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
   8668     b       common_exceptionThrown      @ no, handle exception
   8669 
   8670 /* continuation for OP_SPUT_OBJECT */
   8671 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
   8672     mov     r2, rINST, lsr #8           @ r2<- AA
   8673     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8674     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   8675     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8676     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
   8677     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8678     @ no-op                             @ releasing store
   8679     str     r1, [r0, #offStaticField_value]  @ field<- vAA
   8680     cmp     r1, #0                      @ stored a null object?
   8681     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
   8682     GOTO_OPCODE(ip)                     @ jump to next instruction
   8683 
   8684 /* continuation for OP_SPUT_BOOLEAN */
   8685 
   8686     /*
   8687      * Continuation if the field has not yet been resolved.
   8688      *  r1: BBBB field ref
   8689      */
   8690 .LOP_SPUT_BOOLEAN_resolve:
   8691     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8692     EXPORT_PC()                         @ resolve() could throw, so export now
   8693     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8694     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8695     cmp     r0, #0                      @ success?
   8696     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
   8697     b       common_exceptionThrown      @ no, handle exception
   8698 
   8699 /* continuation for OP_SPUT_BYTE */
   8700 
   8701     /*
   8702      * Continuation if the field has not yet been resolved.
   8703      *  r1: BBBB field ref
   8704      */
   8705 .LOP_SPUT_BYTE_resolve:
   8706     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8707     EXPORT_PC()                         @ resolve() could throw, so export now
   8708     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8709     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8710     cmp     r0, #0                      @ success?
   8711     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
   8712     b       common_exceptionThrown      @ no, handle exception
   8713 
   8714 /* continuation for OP_SPUT_CHAR */
   8715 
   8716     /*
   8717      * Continuation if the field has not yet been resolved.
   8718      *  r1: BBBB field ref
   8719      */
   8720 .LOP_SPUT_CHAR_resolve:
   8721     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8722     EXPORT_PC()                         @ resolve() could throw, so export now
   8723     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8724     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8725     cmp     r0, #0                      @ success?
   8726     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
   8727     b       common_exceptionThrown      @ no, handle exception
   8728 
   8729 /* continuation for OP_SPUT_SHORT */
   8730 
   8731     /*
   8732      * Continuation if the field has not yet been resolved.
   8733      *  r1: BBBB field ref
   8734      */
   8735 .LOP_SPUT_SHORT_resolve:
   8736     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8737     EXPORT_PC()                         @ resolve() could throw, so export now
   8738     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8739     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8740     cmp     r0, #0                      @ success?
   8741     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
   8742     b       common_exceptionThrown      @ no, handle exception
   8743 
   8744 /* continuation for OP_INVOKE_VIRTUAL */
   8745 
   8746     /*
   8747      * At this point:
   8748      *  r0 = resolved base method
   8749      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
   8750      */
   8751 .LOP_INVOKE_VIRTUAL_continue:
   8752     GET_VREG(r1, r10)                   @ r1<- "this" ptr
   8753     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8754     cmp     r1, #0                      @ is "this" null?
   8755     beq     common_errNullObject        @ null "this", throw exception
   8756     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
   8757     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
   8758     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8759     bl      common_invokeMethodNoRange @ continue on
   8760 
   8761 /* continuation for OP_INVOKE_SUPER */
   8762 
   8763     /*
   8764      * At this point:
   8765      *  r0 = resolved base method
   8766      *  r9 = method->clazz
   8767      */
   8768 .LOP_INVOKE_SUPER_continue:
   8769     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
   8770     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8771     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
   8772     EXPORT_PC()                         @ must export for invoke
   8773     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
   8774     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
   8775     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
   8776     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8777     bl      common_invokeMethodNoRange @ continue on
   8778 
   8779 .LOP_INVOKE_SUPER_resolve:
   8780     mov     r0, r9                      @ r0<- method->clazz
   8781     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   8782     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8783     cmp     r0, #0                      @ got null?
   8784     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
   8785     b       common_exceptionThrown      @ yes, handle exception
   8786 
   8787     /*
   8788      * Throw a NoSuchMethodError with the method name as the message.
   8789      *  r0 = resolved base method
   8790      */
   8791 .LOP_INVOKE_SUPER_nsm:
   8792     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
   8793     b       common_errNoSuchMethod
   8794 
   8795 /* continuation for OP_INVOKE_DIRECT */
   8796 
   8797     /*
   8798      * On entry:
   8799      *  r1 = reference (BBBB or CCCC)
   8800      *  r10 = "this" register
   8801      */
   8802 .LOP_INVOKE_DIRECT_resolve:
   8803     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8804     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8805     mov     r2, #METHOD_DIRECT          @ resolver method type
   8806     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8807     cmp     r0, #0                      @ got null?
   8808     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
   8809     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
   8810     b       common_exceptionThrown      @ yes, handle exception
   8811 
   8812 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
   8813 
   8814     /*
   8815      * At this point:
   8816      *  r0 = resolved base method
   8817      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
   8818      */
   8819 .LOP_INVOKE_VIRTUAL_RANGE_continue:
   8820     GET_VREG(r1, r10)                   @ r1<- "this" ptr
   8821     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8822     cmp     r1, #0                      @ is "this" null?
   8823     beq     common_errNullObject        @ null "this", throw exception
   8824     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
   8825     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
   8826     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8827     bl      common_invokeMethodRange @ continue on
   8828 
   8829 /* continuation for OP_INVOKE_SUPER_RANGE */
   8830 
   8831     /*
   8832      * At this point:
   8833      *  r0 = resolved base method
   8834      *  r9 = method->clazz
   8835      */
   8836 .LOP_INVOKE_SUPER_RANGE_continue:
   8837     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
   8838     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8839     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
   8840     EXPORT_PC()                         @ must export for invoke
   8841     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
   8842     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
   8843     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
   8844     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8845     bl      common_invokeMethodRange @ continue on
   8846 
   8847 .LOP_INVOKE_SUPER_RANGE_resolve:
   8848     mov     r0, r9                      @ r0<- method->clazz
   8849     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   8850     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8851     cmp     r0, #0                      @ got null?
   8852     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
   8853     b       common_exceptionThrown      @ yes, handle exception
   8854 
   8855     /*
   8856      * Throw a NoSuchMethodError with the method name as the message.
   8857      *  r0 = resolved base method
   8858      */
   8859 .LOP_INVOKE_SUPER_RANGE_nsm:
   8860     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
   8861     b       common_errNoSuchMethod
   8862 
   8863 /* continuation for OP_INVOKE_DIRECT_RANGE */
   8864 
   8865     /*
   8866      * On entry:
   8867      *  r1 = reference (BBBB or CCCC)
   8868      *  r10 = "this" register
   8869      */
   8870 .LOP_INVOKE_DIRECT_RANGE_resolve:
   8871     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8872     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8873     mov     r2, #METHOD_DIRECT          @ resolver method type
   8874     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8875     cmp     r0, #0                      @ got null?
   8876     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
   8877     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
   8878     b       common_exceptionThrown      @ yes, handle exception
   8879 
   8880 /* continuation for OP_FLOAT_TO_LONG */
   8881 /*
   8882  * Convert the float in r0 to a long in r0/r1.
   8883  *
   8884  * We have to clip values to long min/max per the specification.  The
   8885  * expected common case is a "reasonable" value that converts directly
   8886  * to modest integer.  The EABI convert function isn't doing this for us.
   8887  */
   8888 f2l_doconv:
   8889     stmfd   sp!, {r4, lr}
   8890     mov     r1, #0x5f000000             @ (float)maxlong
   8891     mov     r4, r0
   8892     bl      __aeabi_fcmpge              @ is arg >= maxlong?
   8893     cmp     r0, #0                      @ nonzero == yes
   8894     mvnne   r0, #0                      @ return maxlong (7fffffff)
   8895     mvnne   r1, #0x80000000
   8896     ldmnefd sp!, {r4, pc}
   8897 
   8898     mov     r0, r4                      @ recover arg
   8899     mov     r1, #0xdf000000             @ (float)minlong
   8900     bl      __aeabi_fcmple              @ is arg <= minlong?
   8901     cmp     r0, #0                      @ nonzero == yes
   8902     movne   r0, #0                      @ return minlong (80000000)
   8903     movne   r1, #0x80000000
   8904     ldmnefd sp!, {r4, pc}
   8905 
   8906     mov     r0, r4                      @ recover arg
   8907     mov     r1, r4
   8908     bl      __aeabi_fcmpeq              @ is arg == self?
   8909     cmp     r0, #0                      @ zero == no
   8910     moveq   r1, #0                      @ return zero for NaN
   8911     ldmeqfd sp!, {r4, pc}
   8912 
   8913     mov     r0, r4                      @ recover arg
   8914     bl      __aeabi_f2lz                @ convert float to long
   8915     ldmfd   sp!, {r4, pc}
   8916 
   8917 /* continuation for OP_DOUBLE_TO_LONG */
   8918 /*
   8919  * Convert the double in r0/r1 to a long in r0/r1.
   8920  *
   8921  * We have to clip values to long min/max per the specification.  The
   8922  * expected common case is a "reasonable" value that converts directly
   8923  * to modest integer.  The EABI convert function isn't doing this for us.
   8924  */
   8925 d2l_doconv:
   8926     stmfd   sp!, {r4, r5, lr}           @ save regs
   8927     mov     r3, #0x43000000             @ maxlong, as a double (high word)
   8928     add     r3, #0x00e00000             @  0x43e00000
   8929     mov     r2, #0                      @ maxlong, as a double (low word)
   8930     sub     sp, sp, #4                  @ align for EABI
   8931     mov     r4, r0                      @ save a copy of r0
   8932     mov     r5, r1                      @  and r1
   8933     bl      __aeabi_dcmpge              @ is arg >= maxlong?
   8934     cmp     r0, #0                      @ nonzero == yes
   8935     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
   8936     mvnne   r1, #0x80000000
   8937     bne     1f
   8938 
   8939     mov     r0, r4                      @ recover arg
   8940     mov     r1, r5
   8941     mov     r3, #0xc3000000             @ minlong, as a double (high word)
   8942     add     r3, #0x00e00000             @  0xc3e00000
   8943     mov     r2, #0                      @ minlong, as a double (low word)
   8944     bl      __aeabi_dcmple              @ is arg <= minlong?
   8945     cmp     r0, #0                      @ nonzero == yes
   8946     movne   r0, #0                      @ return minlong (8000000000000000)
   8947     movne   r1, #0x80000000
   8948     bne     1f
   8949 
   8950     mov     r0, r4                      @ recover arg
   8951     mov     r1, r5
   8952     mov     r2, r4                      @ compare against self
   8953     mov     r3, r5
   8954     bl      __aeabi_dcmpeq              @ is arg == self?
   8955     cmp     r0, #0                      @ zero == no
   8956     moveq   r1, #0                      @ return zero for NaN
   8957     beq     1f
   8958 
   8959     mov     r0, r4                      @ recover arg
   8960     mov     r1, r5
   8961     bl      __aeabi_d2lz                @ convert double to long
   8962 
   8963 1:
   8964     add     sp, sp, #4
   8965     ldmfd   sp!, {r4, r5, pc}
   8966 
   8967 /* continuation for OP_MUL_LONG */
   8968 
   8969 .LOP_MUL_LONG_finish:
   8970     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8971     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
   8972     GOTO_OPCODE(ip)                     @ jump to next instruction
   8973 
   8974 /* continuation for OP_SHL_LONG */
   8975 
   8976 .LOP_SHL_LONG_finish:
   8977     mov     r0, r0, asl r2              @  r0<- r0 << r2
   8978     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8979     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   8980     GOTO_OPCODE(ip)                     @ jump to next instruction
   8981 
   8982 /* continuation for OP_SHR_LONG */
   8983 
   8984 .LOP_SHR_LONG_finish:
   8985     mov     r1, r1, asr r2              @  r1<- r1 >> r2
   8986     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8987     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   8988     GOTO_OPCODE(ip)                     @ jump to next instruction
   8989 
   8990 /* continuation for OP_USHR_LONG */
   8991 
   8992 .LOP_USHR_LONG_finish:
   8993     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
   8994     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8995     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   8996     GOTO_OPCODE(ip)                     @ jump to next instruction
   8997 
   8998 /* continuation for OP_SHL_LONG_2ADDR */
   8999 
   9000 .LOP_SHL_LONG_2ADDR_finish:
   9001     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9002     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9003     GOTO_OPCODE(ip)                     @ jump to next instruction
   9004 
   9005 /* continuation for OP_SHR_LONG_2ADDR */
   9006 
   9007 .LOP_SHR_LONG_2ADDR_finish:
   9008     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9009     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9010     GOTO_OPCODE(ip)                     @ jump to next instruction
   9011 
   9012 /* continuation for OP_USHR_LONG_2ADDR */
   9013 
   9014 .LOP_USHR_LONG_2ADDR_finish:
   9015     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9016     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9017     GOTO_OPCODE(ip)                     @ jump to next instruction
   9018 
   9019 /* continuation for OP_IGET_VOLATILE */
   9020 
   9021     /*
   9022      * Currently:
   9023      *  r0 holds resolved field
   9024      *  r9 holds object
   9025      */
   9026 .LOP_IGET_VOLATILE_finish:
   9027     @bl      common_squeak0
   9028     cmp     r9, #0                      @ check object for null
   9029     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9030     beq     common_errNullObject        @ object was null
   9031     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   9032     SMP_DMB                            @ acquiring load
   9033     mov     r2, rINST, lsr #8           @ r2<- A+
   9034     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9035     and     r2, r2, #15                 @ r2<- A
   9036     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9037     SET_VREG(r0, r2)                    @ fp[A]<- r0
   9038     GOTO_OPCODE(ip)                     @ jump to next instruction
   9039 
   9040 /* continuation for OP_IPUT_VOLATILE */
   9041 
   9042     /*
   9043      * Currently:
   9044      *  r0 holds resolved field
   9045      *  r9 holds object
   9046      */
   9047 .LOP_IPUT_VOLATILE_finish:
   9048     @bl      common_squeak0
   9049     mov     r1, rINST, lsr #8           @ r1<- A+
   9050     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9051     and     r1, r1, #15                 @ r1<- A
   9052     cmp     r9, #0                      @ check object for null
   9053     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9054     beq     common_errNullObject        @ object was null
   9055     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9056     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9057     SMP_DMB                            @ releasing store
   9058     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   9059     GOTO_OPCODE(ip)                     @ jump to next instruction
   9060 
   9061 /* continuation for OP_SGET_VOLATILE */
   9062 
   9063     /*
   9064      * Continuation if the field has not yet been resolved.
   9065      *  r1: BBBB field ref
   9066      */
   9067 .LOP_SGET_VOLATILE_resolve:
   9068     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9069     EXPORT_PC()                         @ resolve() could throw, so export now
   9070     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9071     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9072     cmp     r0, #0                      @ success?
   9073     bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
   9074     b       common_exceptionThrown      @ no, handle exception
   9075 
   9076 /* continuation for OP_SPUT_VOLATILE */
   9077 
   9078     /*
   9079      * Continuation if the field has not yet been resolved.
   9080      *  r1: BBBB field ref
   9081      */
   9082 .LOP_SPUT_VOLATILE_resolve:
   9083     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9084     EXPORT_PC()                         @ resolve() could throw, so export now
   9085     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9086     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9087     cmp     r0, #0                      @ success?
   9088     bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
   9089     b       common_exceptionThrown      @ no, handle exception
   9090 
   9091 /* continuation for OP_IGET_OBJECT_VOLATILE */
   9092 
   9093     /*
   9094      * Currently:
   9095      *  r0 holds resolved field
   9096      *  r9 holds object
   9097      */
   9098 .LOP_IGET_OBJECT_VOLATILE_finish:
   9099     @bl      common_squeak0
   9100     cmp     r9, #0                      @ check object for null
   9101     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9102     beq     common_errNullObject        @ object was null
   9103     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   9104     SMP_DMB                            @ acquiring load
   9105     mov     r2, rINST, lsr #8           @ r2<- A+
   9106     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9107     and     r2, r2, #15                 @ r2<- A
   9108     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9109     SET_VREG(r0, r2)                    @ fp[A]<- r0
   9110     GOTO_OPCODE(ip)                     @ jump to next instruction
   9111 
   9112 /* continuation for OP_IGET_WIDE_VOLATILE */
   9113 
   9114     /*
   9115      * Currently:
   9116      *  r0 holds resolved field
   9117      *  r9 holds object
   9118      */
   9119 .LOP_IGET_WIDE_VOLATILE_finish:
   9120     cmp     r9, #0                      @ check object for null
   9121     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9122     beq     common_errNullObject        @ object was null
   9123     .if     1
   9124     add     r0, r9, r3                  @ r0<- address of field
   9125     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   9126     .else
   9127     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
   9128     .endif
   9129     mov     r2, rINST, lsr #8           @ r2<- A+
   9130     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9131     and     r2, r2, #15                 @ r2<- A
   9132     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   9133     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9134     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   9135     GOTO_OPCODE(ip)                     @ jump to next instruction
   9136 
   9137 /* continuation for OP_IPUT_WIDE_VOLATILE */
   9138 
   9139     /*
   9140      * Currently:
   9141      *  r0 holds resolved field
   9142      *  r9 holds object
   9143      */
   9144 .LOP_IPUT_WIDE_VOLATILE_finish:
   9145     mov     r2, rINST, lsr #8           @ r2<- A+
   9146     cmp     r9, #0                      @ check object for null
   9147     and     r2, r2, #15                 @ r2<- A
   9148     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9149     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
   9150     beq     common_errNullObject        @ object was null
   9151     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9152     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
   9153     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   9154     .if     1
   9155     add     r2, r9, r3                  @ r2<- target address
   9156     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   9157     .else
   9158     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
   9159     .endif
   9160     GOTO_OPCODE(r10)                    @ jump to next instruction
   9161 
   9162 /* continuation for OP_SGET_WIDE_VOLATILE */
   9163 
   9164     /*
   9165      * Continuation if the field has not yet been resolved.
   9166      *  r1: BBBB field ref
   9167      *
   9168      * Returns StaticField pointer in r0.
   9169      */
   9170 .LOP_SGET_WIDE_VOLATILE_resolve:
   9171     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9172     EXPORT_PC()                         @ resolve() could throw, so export now
   9173     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9174     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9175     cmp     r0, #0                      @ success?
   9176     bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
   9177     b       common_exceptionThrown      @ no, handle exception
   9178 
   9179 /* continuation for OP_SPUT_WIDE_VOLATILE */
   9180 
   9181     /*
   9182      * Continuation if the field has not yet been resolved.
   9183      *  r1: BBBB field ref
   9184      *  r9: &fp[AA]
   9185      *
   9186      * Returns StaticField pointer in r2.
   9187      */
   9188 .LOP_SPUT_WIDE_VOLATILE_resolve:
   9189     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9190     EXPORT_PC()                         @ resolve() could throw, so export now
   9191     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9192     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9193     cmp     r0, #0                      @ success?
   9194     mov     r2, r0                      @ copy to r2
   9195     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
   9196     b       common_exceptionThrown      @ no, handle exception
   9197 
   9198 /* continuation for OP_EXECUTE_INLINE */
   9199 
   9200     /*
   9201      * Extract args, call function.
   9202      *  r0 = #of args (0-4)
   9203      *  r10 = call index
   9204      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
   9205      *
   9206      * Other ideas:
   9207      * - Use a jump table from the main piece to jump directly into the
   9208      *   AND/LDR pairs.  Costs a data load, saves a branch.
   9209      * - Have five separate pieces that do the loading, so we can work the
   9210      *   interleave a little better.  Increases code size.
   9211      */
   9212 .LOP_EXECUTE_INLINE_continue:
   9213     rsb     r0, r0, #4                  @ r0<- 4-r0
   9214     FETCH(r9, 2)                        @ r9<- FEDC
   9215     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
   9216     bl      common_abort                @ (skipped due to ARM prefetch)
   9217 4:  and     ip, r9, #0xf000             @ isolate F
   9218     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
   9219 3:  and     ip, r9, #0x0f00             @ isolate E
   9220     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
   9221 2:  and     ip, r9, #0x00f0             @ isolate D
   9222     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
   9223 1:  and     ip, r9, #0x000f             @ isolate C
   9224     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
   9225 0:
   9226     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
   9227     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
   9228     @ (not reached)
   9229 
   9230 .LOP_EXECUTE_INLINE_table:
   9231     .word   gDvmInlineOpsTable
   9232 
   9233 /* continuation for OP_EXECUTE_INLINE_RANGE */
   9234 
   9235     /*
   9236      * Extract args, call function.
   9237      *  r0 = #of args (0-4)
   9238      *  r10 = call index
   9239      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
   9240      */
   9241 .LOP_EXECUTE_INLINE_RANGE_continue:
   9242     rsb     r0, r0, #4                  @ r0<- 4-r0
   9243     FETCH(r9, 2)                        @ r9<- CCCC
   9244     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
   9245     bl      common_abort                @ (skipped due to ARM prefetch)
   9246 4:  add     ip, r9, #3                  @ base+3
   9247     GET_VREG(r3, ip)                    @ r3<- vBase[3]
   9248 3:  add     ip, r9, #2                  @ base+2
   9249     GET_VREG(r2, ip)                    @ r2<- vBase[2]
   9250 2:  add     ip, r9, #1                  @ base+1
   9251     GET_VREG(r1, ip)                    @ r1<- vBase[1]
   9252 1:  add     ip, r9, #0                  @ (nop)
   9253     GET_VREG(r0, ip)                    @ r0<- vBase[0]
   9254 0:
   9255     ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
   9256     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
   9257     @ (not reached)
   9258 
   9259 .LOP_EXECUTE_INLINE_RANGE_table:
   9260     .word   gDvmInlineOpsTable
   9261 
   9262 /* continuation for OP_IPUT_OBJECT_VOLATILE */
   9263 
   9264     /*
   9265      * Currently:
   9266      *  r0 holds resolved field
   9267      *  r9 holds object
   9268      */
   9269 .LOP_IPUT_OBJECT_VOLATILE_finish:
   9270     @bl      common_squeak0
   9271     mov     r1, rINST, lsr #8           @ r1<- A+
   9272     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9273     and     r1, r1, #15                 @ r1<- A
   9274     cmp     r9, #0                      @ check object for null
   9275     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9276     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9277     beq     common_errNullObject        @ object was null
   9278     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9279     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9280     SMP_DMB                            @ releasing store
   9281     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
   9282     cmp     r0, #0                      @ stored a null reference?
   9283     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
   9284     GOTO_OPCODE(ip)                     @ jump to next instruction
   9285 
   9286 /* continuation for OP_SGET_OBJECT_VOLATILE */
   9287 
   9288     /*
   9289      * Continuation if the field has not yet been resolved.
   9290      *  r1: BBBB field ref
   9291      */
   9292 .LOP_SGET_OBJECT_VOLATILE_resolve:
   9293     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9294     EXPORT_PC()                         @ resolve() could throw, so export now
   9295     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9296     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9297     cmp     r0, #0                      @ success?
   9298     bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
   9299     b       common_exceptionThrown      @ no, handle exception
   9300 
   9301 /* continuation for OP_SPUT_OBJECT_VOLATILE */
   9302 .LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
   9303     mov     r2, rINST, lsr #8           @ r2<- AA
   9304     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9305     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   9306     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9307     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
   9308     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9309     SMP_DMB                            @ releasing store
   9310     str     r1, [r0, #offStaticField_value]  @ field<- vAA
   9311     cmp     r1, #0                      @ stored a null object?
   9312     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
   9313     GOTO_OPCODE(ip)                     @ jump to next instruction
   9314 
   9315     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
   9316     .global dvmAsmSisterEnd
   9317 dvmAsmSisterEnd:
   9318 
   9319 /* File: armv5te/footer.S */
   9320 
   9321 /*
   9322  * ===========================================================================
   9323  *  Common subroutines and data
   9324  * ===========================================================================
   9325  */
   9326 
   9327 
   9328 
   9329     .text
   9330     .align  2
   9331 
   9332 #if defined(WITH_JIT)
   9333 #if defined(WITH_SELF_VERIFICATION)
   9334     .global dvmJitToInterpPunt
   9335 dvmJitToInterpPunt:
   9336     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9337     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
   9338     mov    r3, #0
   9339     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9340     b      jitSVShadowRunEnd            @ doesn't return
   9341 
   9342     .global dvmJitToInterpSingleStep
   9343 dvmJitToInterpSingleStep:
   9344     str    lr,[rGLUE,#offGlue_jitResumeNPC]
   9345     str    r1,[rGLUE,#offGlue_jitResumeDPC]
   9346     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
   9347     b      jitSVShadowRunEnd            @ doesn't return
   9348 
   9349     .global dvmJitToInterpNoChainNoProfile
   9350 dvmJitToInterpNoChainNoProfile:
   9351     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9352     mov    r0,rPC                       @ pass our target PC
   9353     mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
   9354     mov    r3, #0                       @ 0 means !inJitCodeCache
   9355     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
   9356     b      jitSVShadowRunEnd            @ doesn't return
   9357 
   9358     .global dvmJitToInterpTraceSelectNoChain
   9359 dvmJitToInterpTraceSelectNoChain:
   9360     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9361     mov    r0,rPC                       @ pass our target PC
   9362     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
   9363     mov    r3, #0                       @ 0 means !inJitCodeCache
   9364     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9365     b      jitSVShadowRunEnd            @ doesn't return
   9366 
   9367     .global dvmJitToInterpTraceSelect
   9368 dvmJitToInterpTraceSelect:
   9369     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9370     ldr    r0,[lr, #-1]                 @ pass our target PC
   9371     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
   9372     mov    r3, #0                       @ 0 means !inJitCodeCache
   9373     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9374     b      jitSVShadowRunEnd            @ doesn't return
   9375 
   9376     .global dvmJitToInterpBackwardBranch
   9377 dvmJitToInterpBackwardBranch:
   9378     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9379     ldr    r0,[lr, #-1]                 @ pass our target PC
   9380     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
   9381     mov    r3, #0                       @ 0 means !inJitCodeCache
   9382     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9383     b      jitSVShadowRunEnd            @ doesn't return
   9384 
   9385     .global dvmJitToInterpNormal
   9386 dvmJitToInterpNormal:
   9387     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9388     ldr    r0,[lr, #-1]                 @ pass our target PC
   9389     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
   9390     mov    r3, #0                       @ 0 means !inJitCodeCache
   9391     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9392     b      jitSVShadowRunEnd            @ doesn't return
   9393 
   9394     .global dvmJitToInterpNoChain
   9395 dvmJitToInterpNoChain:
   9396     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9397     mov    r0,rPC                       @ pass our target PC
   9398     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
   9399     mov    r3, #0                       @ 0 means !inJitCodeCache
   9400     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9401     b      jitSVShadowRunEnd            @ doesn't return
   9402 #else
   9403 /*
   9404  * Return from the translation cache to the interpreter when the compiler is
   9405  * having issues translating/executing a Dalvik instruction. We have to skip
   9406  * the code cache lookup otherwise it is possible to indefinitely bouce
   9407  * between the interpreter and the code cache if the instruction that fails
   9408  * to be compiled happens to be at a trace start.
   9409  */
   9410     .global dvmJitToInterpPunt
   9411 dvmJitToInterpPunt:
   9412     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9413     mov    rPC, r0
   9414 #if defined(WITH_JIT_TUNING)
   9415     mov    r0,lr
   9416     bl     dvmBumpPunt;
   9417 #endif
   9418     EXPORT_PC()
   9419     mov    r0, #0
   9420     str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9421     adrl   rIBASE, dvmAsmInstructionStart
   9422     FETCH_INST()
   9423     GET_INST_OPCODE(ip)
   9424     GOTO_OPCODE(ip)
   9425 
   9426 /*
   9427  * Return to the interpreter to handle a single instruction.
   9428  * On entry:
   9429  *    r0 <= PC
   9430  *    r1 <= PC of resume instruction
   9431  *    lr <= resume point in translation
   9432  */
   9433     .global dvmJitToInterpSingleStep
   9434 dvmJitToInterpSingleStep:
   9435     str    lr,[rGLUE,#offGlue_jitResumeNPC]
   9436     str    r1,[rGLUE,#offGlue_jitResumeDPC]
   9437     mov    r1,#kInterpEntryInstr
   9438     @ enum is 4 byte in aapcs-EABI
   9439     str    r1, [rGLUE, #offGlue_entryPoint]
   9440     mov    rPC,r0
   9441     EXPORT_PC()
   9442 
   9443     adrl   rIBASE, dvmAsmInstructionStart
   9444     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
   9445     str    r2,[rGLUE,#offGlue_jitState]
   9446     mov    r1,#1                  @ set changeInterp to bail to debug interp
   9447     b      common_gotoBail
   9448 
   9449 /*
   9450  * Return from the translation cache and immediately request
   9451  * a translation for the exit target.  Commonly used for callees.
   9452  */
   9453     .global dvmJitToInterpTraceSelectNoChain
   9454 dvmJitToInterpTraceSelectNoChain:
   9455 #if defined(WITH_JIT_TUNING)
   9456     bl     dvmBumpNoChain
   9457 #endif
   9458     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9459     mov    r0,rPC
   9460     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9461     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9462     mov    r1, rPC                  @ arg1 of translation may need this
   9463     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9464     cmp    r0,#0                    @ !0 means translation exists
   9465     bxne   r0                       @ continue native execution if so
   9466     b      2f                       @ branch over to use the interpreter
   9467 
   9468 /*
   9469  * Return from the translation cache and immediately request
   9470  * a translation for the exit target.  Commonly used following
   9471  * invokes.
   9472  */
   9473     .global dvmJitToInterpTraceSelect
   9474 dvmJitToInterpTraceSelect:
   9475     ldr    rPC,[lr, #-1]           @ get our target PC
   9476     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9477     add    rINST,lr,#-5            @ save start of chain branch
   9478     add    rINST, #-4              @  .. which is 9 bytes back
   9479     mov    r0,rPC
   9480     bl     dvmJitGetCodeAddr       @ Is there a translation?
   9481     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9482     cmp    r0,#0
   9483     beq    2f
   9484     mov    r1,rINST
   9485     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
   9486     mov    r1, rPC                  @ arg1 of translation may need this
   9487     mov    lr, #0                   @ in case target is HANDLER_INTERPRET
   9488     cmp    r0,#0                    @ successful chain?
   9489     bxne   r0                       @ continue native execution
   9490     b      toInterpreter            @ didn't chain - resume with interpreter
   9491 
   9492 /* No translation, so request one if profiling isn't disabled*/
   9493 2:
   9494     adrl   rIBASE, dvmAsmInstructionStart
   9495     GET_JIT_PROF_TABLE(r0)
   9496     FETCH_INST()
   9497     cmp    r0, #0
   9498     movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
   9499     bne    common_selectTrace
   9500     GET_INST_OPCODE(ip)
   9501     GOTO_OPCODE(ip)
   9502 
   9503 /*
   9504  * Return from the translation cache to the interpreter.
   9505  * The return was done with a BLX from thumb mode, and
   9506  * the following 32-bit word contains the target rPC value.
   9507  * Note that lr (r14) will have its low-order bit set to denote
   9508  * its thumb-mode origin.
   9509  *
   9510  * We'll need to stash our lr origin away, recover the new
   9511  * target and then check to see if there is a translation available
   9512  * for our new target.  If so, we do a translation chain and
   9513  * go back to native execution.  Otherwise, it's back to the
   9514  * interpreter (after treating this entry as a potential
   9515  * trace start).
   9516  */
   9517     .global dvmJitToInterpNormal
   9518 dvmJitToInterpNormal:
   9519     ldr    rPC,[lr, #-1]           @ get our target PC
   9520     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9521     add    rINST,lr,#-5            @ save start of chain branch
   9522     add    rINST,#-4               @ .. which is 9 bytes back
   9523 #if defined(WITH_JIT_TUNING)
   9524     bl     dvmBumpNormal
   9525 #endif
   9526     mov    r0,rPC
   9527     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9528     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9529     cmp    r0,#0
   9530     beq    toInterpreter            @ go if not, otherwise do chain
   9531     mov    r1,rINST
   9532     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
   9533     mov    r1, rPC                  @ arg1 of translation may need this
   9534     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9535     cmp    r0,#0                    @ successful chain?
   9536     bxne   r0                       @ continue native execution
   9537     b      toInterpreter            @ didn't chain - resume with interpreter
   9538 
   9539 /*
   9540  * Return from the translation cache to the interpreter to do method invocation.
   9541  * Check if translation exists for the callee, but don't chain to it.
   9542  */
   9543     .global dvmJitToInterpNoChainNoProfile
   9544 dvmJitToInterpNoChainNoProfile:
   9545 #if defined(WITH_JIT_TUNING)
   9546     bl     dvmBumpNoChain
   9547 #endif
   9548     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9549     mov    r0,rPC
   9550     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9551     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9552     mov    r1, rPC                  @ arg1 of translation may need this
   9553     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9554     cmp    r0,#0
   9555     bxne   r0                       @ continue native execution if so
   9556     EXPORT_PC()
   9557     adrl   rIBASE, dvmAsmInstructionStart
   9558     FETCH_INST()
   9559     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9560     GOTO_OPCODE(ip)                     @ jump to next instruction
   9561 
   9562 /*
   9563  * Return from the translation cache to the interpreter to do method invocation.
   9564  * Check if translation exists for the callee, but don't chain to it.
   9565  */
   9566     .global dvmJitToInterpNoChain
   9567 dvmJitToInterpNoChain:
   9568 #if defined(WITH_JIT_TUNING)
   9569     bl     dvmBumpNoChain
   9570 #endif
   9571     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9572     mov    r0,rPC
   9573     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9574     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9575     mov    r1, rPC                  @ arg1 of translation may need this
   9576     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9577     cmp    r0,#0
   9578     bxne   r0                       @ continue native execution if so
   9579 #endif
   9580 
   9581 /*
   9582  * No translation, restore interpreter regs and start interpreting.
   9583  * rGLUE & rFP were preserved in the translated code, and rPC has
   9584  * already been restored by the time we get here.  We'll need to set
   9585  * up rIBASE & rINST, and load the address of the JitTable into r0.
   9586  */
   9587 toInterpreter:
   9588     EXPORT_PC()
   9589     adrl   rIBASE, dvmAsmInstructionStart
   9590     FETCH_INST()
   9591     GET_JIT_PROF_TABLE(r0)
   9592     @ NOTE: intended fallthrough
   9593 
   9594 /*
   9595  * Common code to update potential trace start counter, and initiate
   9596  * a trace-build if appropriate.  On entry, rPC should point to the
   9597  * next instruction to execute, and rINST should be already loaded with
   9598  * the next opcode word, and r0 holds a pointer to the jit profile
   9599  * table (pJitProfTable).
   9600  */
   9601 common_testUpdateProfile:
   9602     cmp     r0,#0
   9603     GET_INST_OPCODE(ip)
   9604     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
   9605 
   9606 common_updateProfile:
   9607     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
   9608     lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
   9609     ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
   9610     GET_INST_OPCODE(ip)
   9611     subs    r1,r1,#1           @ decrement counter
   9612     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
   9613     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
   9614 
   9615 /*
   9616  * Here, we switch to the debug interpreter to request
   9617  * trace selection.  First, though, check to see if there
   9618  * is already a native translation in place (and, if so,
   9619  * jump to it now).
   9620  */
   9621     GET_JIT_THRESHOLD(r1)
   9622     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
   9623     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
   9624     EXPORT_PC()
   9625     mov     r0,rPC
   9626     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
   9627     str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9628     mov     r1, rPC                     @ arg1 of translation may need this
   9629     mov     lr, #0                      @  in case target is HANDLER_INTERPRET
   9630     cmp     r0,#0
   9631 #if !defined(WITH_SELF_VERIFICATION)
   9632     bxne    r0                          @ jump to the translation
   9633     mov     r2,#kJitTSelectRequest      @ ask for trace selection
   9634     @ fall-through to common_selectTrace
   9635 #else
   9636     moveq   r2,#kJitTSelectRequest      @ ask for trace selection
   9637     beq     common_selectTrace
   9638     /*
   9639      * At this point, we have a target translation.  However, if
   9640      * that translation is actually the interpret-only pseudo-translation
   9641      * we want to treat it the same as no translation.
   9642      */
   9643     mov     r10, r0                     @ save target
   9644     bl      dvmCompilerGetInterpretTemplate
   9645     cmp     r0, r10                     @ special case?
   9646     bne     jitSVShadowRunStart         @ set up self verification shadow space
   9647     @ Need to clear the inJitCodeCache flag
   9648     ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
   9649     mov    r3, #0                       @ 0 means not in the JIT code cache
   9650     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
   9651     GET_INST_OPCODE(ip)
   9652     GOTO_OPCODE(ip)
   9653     /* no return */
   9654 #endif
   9655 
   9656 /*
   9657  * On entry:
   9658  *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
   9659  */
   9660 common_selectTrace:
   9661     str     r2,[rGLUE,#offGlue_jitState]
   9662     mov     r2,#kInterpEntryInstr       @ normal entry reason
   9663     str     r2,[rGLUE,#offGlue_entryPoint]
   9664     mov     r1,#1                       @ set changeInterp
   9665     b       common_gotoBail
   9666 
   9667 #if defined(WITH_SELF_VERIFICATION)
   9668 /*
   9669  * Save PC and registers to shadow memory for self verification mode
   9670  * before jumping to native translation.
   9671  * On entry:
   9672  *    rPC, rFP, rGLUE: the values that they should contain
   9673  *    r10: the address of the target translation.
   9674  */
   9675 jitSVShadowRunStart:
   9676     mov     r0,rPC                      @ r0<- program counter
   9677     mov     r1,rFP                      @ r1<- frame pointer
   9678     mov     r2,rGLUE                    @ r2<- InterpState pointer
   9679     mov     r3,r10                      @ r3<- target translation
   9680     bl      dvmSelfVerificationSaveState @ save registers to shadow space
   9681     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
   9682     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
   9683     bx      r10                         @ jump to the translation
   9684 
   9685 /*
   9686  * Restore PC, registers, and interpState to original values
   9687  * before jumping back to the interpreter.
   9688  */
   9689 jitSVShadowRunEnd:
   9690     mov    r1,rFP                        @ pass ending fp
   9691     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
   9692     ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
   9693     ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
   9694     ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
   9695     ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
   9696     cmp    r1,#0                         @ check for punt condition
   9697     beq    1f
   9698     mov    r2,#kJitSelfVerification      @ ask for self verification
   9699     str    r2,[rGLUE,#offGlue_jitState]
   9700     mov    r2,#kInterpEntryInstr         @ normal entry reason
   9701     str    r2,[rGLUE,#offGlue_entryPoint]
   9702     mov    r1,#1                         @ set changeInterp
   9703     b      common_gotoBail
   9704 
   9705 1:                                       @ exit to interpreter without check
   9706     EXPORT_PC()
   9707     adrl   rIBASE, dvmAsmInstructionStart
   9708     FETCH_INST()
   9709     GET_INST_OPCODE(ip)
   9710     GOTO_OPCODE(ip)
   9711 #endif
   9712 
   9713 #endif
   9714 
   9715 /*
   9716  * Common code when a backward branch is taken.
   9717  *
   9718  * TODO: we could avoid a branch by just setting r0 and falling through
   9719  * into the common_periodicChecks code, and having a test on r0 at the
   9720  * end determine if we should return to the caller or update & branch to
   9721  * the next instr.
   9722  *
   9723  * On entry:
   9724  *  r9 is PC adjustment *in bytes*
   9725  */
   9726 common_backwardBranch:
   9727     mov     r0, #kInterpEntryInstr
   9728     bl      common_periodicChecks
   9729 #if defined(WITH_JIT)
   9730     GET_JIT_PROF_TABLE(r0)
   9731     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   9732     cmp     r0,#0
   9733     bne     common_updateProfile
   9734     GET_INST_OPCODE(ip)
   9735     GOTO_OPCODE(ip)
   9736 #else
   9737     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   9738     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9739     GOTO_OPCODE(ip)                     @ jump to next instruction
   9740 #endif
   9741 
   9742 
   9743 /*
   9744  * Need to see if the thread needs to be suspended or debugger/profiler
   9745  * activity has begun.  If so, we suspend the thread or side-exit to
   9746  * the debug interpreter as appropriate.
   9747  *
   9748  * The common case is no activity on any of these, so we want to figure
   9749  * that out quickly.  If something is up, we can then sort out what.
   9750  *
   9751  * We want to be fast if the VM was built without debugger or profiler
   9752  * support, but we also need to recognize that the system is usually
   9753  * shipped with both of these enabled.
   9754  *
   9755  * TODO: reduce this so we're just checking a single location.
   9756  *
   9757  * On entry:
   9758  *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
   9759  *  r9 is trampoline PC adjustment *in bytes*
   9760  */
   9761 common_periodicChecks:
   9762     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
   9763 
   9764     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
   9765     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
   9766 
   9767     ldr     ip, [r3]                    @ ip<- suspendCount (int)
   9768 
   9769     cmp     r1, #0                      @ debugger enabled?
   9770     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
   9771     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
   9772     orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
   9773     orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
   9774 
   9775     bxeq    lr                          @ all zero, return
   9776 
   9777     /*
   9778      * One or more interesting events have happened.  Figure out what.
   9779      *
   9780      * If debugging or profiling are compiled in, we need to disambiguate.
   9781      *
   9782      * r0 still holds the reentry type.
   9783      */
   9784     ldr     ip, [r3]                    @ ip<- suspendCount (int)
   9785     cmp     ip, #0                      @ want suspend?
   9786     beq     1f                          @ no, must be debugger/profiler
   9787 
   9788     stmfd   sp!, {r0, lr}               @ preserve r0 and lr
   9789 #if defined(WITH_JIT)
   9790     /*
   9791      * Refresh the Jit's cached copy of profile table pointer.  This pointer
   9792      * doubles as the Jit's on/off switch.
   9793      */
   9794     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
   9795     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   9796     ldr     r3, [r3] @ r3 <- pJitProfTable
   9797     EXPORT_PC()                         @ need for precise GC
   9798     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
   9799 #else
   9800     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   9801     EXPORT_PC()                         @ need for precise GC
   9802 #endif
   9803     bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
   9804     ldmfd   sp!, {r0, lr}               @ restore r0 and lr
   9805 
   9806     /*
   9807      * Reload the debugger/profiler enable flags.  We're checking to see
   9808      * if either of these got set while we were suspended.
   9809      *
   9810      * We can't really avoid the #ifdefs here, because the fields don't
   9811      * exist when the feature is disabled.
   9812      */
   9813     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
   9814     cmp     r1, #0                      @ debugger enabled?
   9815     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
   9816     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
   9817     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
   9818 
   9819     orrs    r1, r1, r2
   9820     beq     2f
   9821 
   9822 1:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
   9823     str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
   9824     add     rPC, rPC, r9                @ update rPC
   9825     mov     r1, #1                      @ "want switch" = true
   9826     b       common_gotoBail             @ side exit
   9827 
   9828 2:
   9829     bx      lr                          @ nothing to do, return
   9830 
   9831 
   9832 /*
   9833  * The equivalent of "goto bail", this calls through the "bail handler".
   9834  *
   9835  * State registers will be saved to the "glue" area before bailing.
   9836  *
   9837  * On entry:
   9838  *  r1 is "bool changeInterp", indicating if we want to switch to the
   9839  *     other interpreter or just bail all the way out
   9840  */
   9841 common_gotoBail:
   9842     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
   9843     mov     r0, rGLUE                   @ r0<- glue ptr
   9844     b       dvmMterpStdBail             @ call(glue, changeInterp)
   9845 
   9846     @add     r1, r1, #1                  @ using (boolean+1)
   9847     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
   9848     @bl      _longjmp                    @ does not return
   9849     @bl      common_abort
   9850 
   9851 
   9852 /*
   9853  * Common code for method invocation with range.
   9854  *
   9855  * On entry:
   9856  *  r0 is "Method* methodToCall", the method we're trying to call
   9857  */
   9858 common_invokeMethodRange:
   9859 .LinvokeNewRange:
   9860     @ prepare to copy args to "outs" area of current frame
   9861     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
   9862     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
   9863     beq     .LinvokeArgsDone            @ if no args, skip the rest
   9864     FETCH(r1, 2)                        @ r1<- CCCC
   9865 
   9866     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
   9867     @ (very few methods have > 10 args; could unroll for common cases)
   9868     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
   9869     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
   9870     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
   9871 1:  ldr     r1, [r3], #4                @ val = *fp++
   9872     subs    r2, r2, #1                  @ count--
   9873     str     r1, [r10], #4               @ *outs++ = val
   9874     bne     1b                          @ ...while count != 0
   9875     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
   9876     b       .LinvokeArgsDone
   9877 
   9878 /*
   9879  * Common code for method invocation without range.
   9880  *
   9881  * On entry:
   9882  *  r0 is "Method* methodToCall", the method we're trying to call
   9883  */
   9884 common_invokeMethodNoRange:
   9885 .LinvokeNewNoRange:
   9886     @ prepare to copy args to "outs" area of current frame
   9887     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
   9888     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
   9889     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
   9890     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
   9891     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
   9892     beq     .LinvokeArgsDone
   9893 
   9894     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
   9895 .LinvokeNonRange:
   9896     rsb     r2, r2, #5                  @ r2<- 5-r2
   9897     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
   9898     bl      common_abort                @ (skipped due to ARM prefetch)
   9899 5:  and     ip, rINST, #0x0f00          @ isolate A
   9900     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
   9901     mov     r0, r0                      @ nop
   9902     str     r2, [r10, #-4]!             @ *--outs = vA
   9903 4:  and     ip, r1, #0xf000             @ isolate G
   9904     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
   9905     mov     r0, r0                      @ nop
   9906     str     r2, [r10, #-4]!             @ *--outs = vG
   9907 3:  and     ip, r1, #0x0f00             @ isolate F
   9908     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
   9909     mov     r0, r0                      @ nop
   9910     str     r2, [r10, #-4]!             @ *--outs = vF
   9911 2:  and     ip, r1, #0x00f0             @ isolate E
   9912     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
   9913     mov     r0, r0                      @ nop
   9914     str     r2, [r10, #-4]!             @ *--outs = vE
   9915 1:  and     ip, r1, #0x000f             @ isolate D
   9916     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
   9917     mov     r0, r0                      @ nop
   9918     str     r2, [r10, #-4]!             @ *--outs = vD
   9919 0:  @ fall through to .LinvokeArgsDone
   9920 
   9921 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
   9922     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
   9923     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
   9924     @ find space for the new stack frame, check for overflow
   9925     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
   9926     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
   9927     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
   9928 @    bl      common_dumpRegs
   9929     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
   9930     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
   9931     cmp     r3, r9                      @ bottom < interpStackEnd?
   9932     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
   9933     blo     .LstackOverflow             @ yes, this frame will overflow stack
   9934 
   9935     @ set up newSaveArea
   9936 #ifdef EASY_GDB
   9937     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
   9938     str     ip, [r10, #offStackSaveArea_prevSave]
   9939 #endif
   9940     str     rFP, [r10, #offStackSaveArea_prevFrame]
   9941     str     rPC, [r10, #offStackSaveArea_savedPc]
   9942 #if defined(WITH_JIT)
   9943     mov     r9, #0
   9944     str     r9, [r10, #offStackSaveArea_returnAddr]
   9945 #endif
   9946     str     r0, [r10, #offStackSaveArea_method]
   9947     tst     r3, #ACC_NATIVE
   9948     bne     .LinvokeNative
   9949 
   9950     /*
   9951     stmfd   sp!, {r0-r3}
   9952     bl      common_printNewline
   9953     mov     r0, rFP
   9954     mov     r1, #0
   9955     bl      dvmDumpFp
   9956     ldmfd   sp!, {r0-r3}
   9957     stmfd   sp!, {r0-r3}
   9958     mov     r0, r1
   9959     mov     r1, r10
   9960     bl      dvmDumpFp
   9961     bl      common_printNewline
   9962     ldmfd   sp!, {r0-r3}
   9963     */
   9964 
   9965     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
   9966     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
   9967     mov     rPC, r2                         @ publish new rPC
   9968     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
   9969 
   9970     @ Update "glue" values for the new method
   9971     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
   9972     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
   9973     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
   9974 #if defined(WITH_JIT)
   9975     GET_JIT_PROF_TABLE(r0)
   9976     mov     rFP, r1                         @ fp = newFp
   9977     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
   9978     mov     rINST, r9                       @ publish new rINST
   9979     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
   9980     cmp     r0,#0
   9981     bne     common_updateProfile
   9982     GOTO_OPCODE(ip)                         @ jump to next instruction
   9983 #else
   9984     mov     rFP, r1                         @ fp = newFp
   9985     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
   9986     mov     rINST, r9                       @ publish new rINST
   9987     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
   9988     GOTO_OPCODE(ip)                         @ jump to next instruction
   9989 #endif
   9990 
   9991 .LinvokeNative:
   9992     @ Prep for the native call
   9993     @ r0=methodToCall, r1=newFp, r10=newSaveArea
   9994     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
   9995     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
   9996     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
   9997     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
   9998     mov     r9, r3                      @ r9<- glue->self (preserve)
   9999 
   10000     mov     r2, r0                      @ r2<- methodToCall
   10001     mov     r0, r1                      @ r0<- newFp (points to args)
   10002     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
   10003 
   10004 #ifdef ASSIST_DEBUGGER
   10005     /* insert fake function header to help gdb find the stack frame */
   10006     b       .Lskip
   10007     .type   dalvik_mterp, %function
   10008 dalvik_mterp:
   10009     .fnstart
   10010     MTERP_ENTRY1
   10011     MTERP_ENTRY2
   10012 .Lskip:
   10013 #endif
   10014 
   10015     @mov     lr, pc                      @ set return addr
   10016     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
   10017     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
   10018 
   10019 #if defined(WITH_JIT)
   10020     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
   10021 #endif
   10022 
   10023     @ native return; r9=self, r10=newSaveArea
   10024     @ equivalent to dvmPopJniLocals
   10025     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
   10026     ldr     r1, [r9, #offThread_exception] @ check for exception
   10027 #if defined(WITH_JIT)
   10028     ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
   10029 #endif
   10030     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
   10031     cmp     r1, #0                      @ null?
   10032     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
   10033 #if defined(WITH_JIT)
   10034     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
   10035 #endif
   10036     bne     common_exceptionThrown      @ no, handle exception
   10037 
   10038     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   10039     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10040     GOTO_OPCODE(ip)                     @ jump to next instruction
   10041 
   10042 .LstackOverflow:    @ r0=methodToCall
   10043     mov     r1, r0                      @ r1<- methodToCall
   10044     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
   10045     bl      dvmHandleStackOverflow
   10046     b       common_exceptionThrown
   10047 #ifdef ASSIST_DEBUGGER
   10048     .fnend
   10049 #endif
   10050 
   10051 
   10052     /*
   10053      * Common code for method invocation, calling through "glue code".
   10054      *
   10055      * TODO: now that we have range and non-range invoke handlers, this
   10056      *       needs to be split into two.  Maybe just create entry points
   10057      *       that set r9 and jump here?
   10058      *
   10059      * On entry:
   10060      *  r0 is "Method* methodToCall", the method we're trying to call
   10061      *  r9 is "bool methodCallRange", indicating if this is a /range variant
   10062      */
   10063      .if    0
   10064 .LinvokeOld:
   10065     sub     sp, sp, #8                  @ space for args + pad
   10066     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
   10067     mov     r2, r0                      @ A2<- methodToCall
   10068     mov     r0, rGLUE                   @ A0<- glue
   10069     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
   10070     mov     r1, r9                      @ A1<- methodCallRange
   10071     mov     r3, rINST, lsr #8           @ A3<- AA
   10072     str     ip, [sp, #0]                @ A4<- ip
   10073     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
   10074     add     sp, sp, #8                  @ remove arg area
   10075     b       common_resumeAfterGlueCall  @ continue to next instruction
   10076     .endif
   10077 
   10078 
   10079 
   10080 /*
   10081  * Common code for handling a return instruction.
   10082  *
   10083  * This does not return.
   10084  */
   10085 common_returnFromMethod:
   10086 .LreturnNew:
   10087     mov     r0, #kInterpEntryReturn
   10088     mov     r9, #0
   10089     bl      common_periodicChecks
   10090 
   10091     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
   10092     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
   10093     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
   10094     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
   10095                                         @ r2<- method we're returning to
   10096     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
   10097     cmp     r2, #0                      @ is this a break frame?
   10098     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
   10099     mov     r1, #0                      @ "want switch" = false
   10100     beq     common_gotoBail             @ break frame, bail out completely
   10101 
   10102     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
   10103     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
   10104     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
   10105     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
   10106 #if defined(WITH_JIT)
   10107     ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
   10108     mov     rPC, r9                     @ publish new rPC
   10109     str     r1, [rGLUE, #offGlue_methodClassDex]
   10110     str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
   10111     cmp     r10, #0                      @ caller is compiled code
   10112     blxne   r10
   10113     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10114     GOTO_OPCODE(ip)                     @ jump to next instruction
   10115 #else
   10116     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10117     mov     rPC, r9                     @ publish new rPC
   10118     str     r1, [rGLUE, #offGlue_methodClassDex]
   10119     GOTO_OPCODE(ip)                     @ jump to next instruction
   10120 #endif
   10121 
   10122     /*
   10123      * Return handling, calls through "glue code".
   10124      */
   10125      .if    0
   10126 .LreturnOld:
   10127     SAVE_PC_FP_TO_GLUE()                @ export state
   10128     mov     r0, rGLUE                   @ arg to function
   10129     bl      dvmMterp_returnFromMethod
   10130     b       common_resumeAfterGlueCall
   10131     .endif
   10132 
   10133 
   10134 /*
   10135  * Somebody has thrown an exception.  Handle it.
   10136  *
   10137  * If the exception processing code returns to us (instead of falling
   10138  * out of the interpreter), continue with whatever the next instruction
   10139  * now happens to be.
   10140  *
   10141  * This does not return.
   10142  */
   10143      .global dvmMterpCommonExceptionThrown
   10144 dvmMterpCommonExceptionThrown:
   10145 common_exceptionThrown:
   10146 .LexceptionNew:
   10147     mov     r0, #kInterpEntryThrow
   10148     mov     r9, #0
   10149     bl      common_periodicChecks
   10150 
   10151     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
   10152     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
   10153     mov     r1, r10                     @ r1<- self
   10154     mov     r0, r9                      @ r0<- exception
   10155     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
   10156     mov     r3, #0                      @ r3<- NULL
   10157     str     r3, [r10, #offThread_exception] @ self->exception = NULL
   10158 
   10159     /* set up args and a local for "&fp" */
   10160     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
   10161     str     rFP, [sp, #-4]!             @ *--sp = fp
   10162     mov     ip, sp                      @ ip<- &fp
   10163     mov     r3, #0                      @ r3<- false
   10164     str     ip, [sp, #-4]!              @ *--sp = &fp
   10165     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
   10166     mov     r0, r10                     @ r0<- self
   10167     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
   10168     mov     r2, r9                      @ r2<- exception
   10169     sub     r1, rPC, r1                 @ r1<- pc - method->insns
   10170     mov     r1, r1, asr #1              @ r1<- offset in code units
   10171 
   10172     /* call, r0 gets catchRelPc (a code-unit offset) */
   10173     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
   10174 
   10175     /* fix earlier stack overflow if necessary; may trash rFP */
   10176     ldrb    r1, [r10, #offThread_stackOverflowed]
   10177     cmp     r1, #0                      @ did we overflow earlier?
   10178     beq     1f                          @ no, skip ahead
   10179     mov     rFP, r0                     @ save relPc result in rFP
   10180     mov     r0, r10                     @ r0<- self
   10181     mov     r1, r9                      @ r1<- exception
   10182     bl      dvmCleanupStackOverflow     @ call(self)
   10183     mov     r0, rFP                     @ restore result
   10184 1:
   10185 
   10186     /* update frame pointer and check result from dvmFindCatchBlock */
   10187     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
   10188     cmp     r0, #0                      @ is catchRelPc < 0?
   10189     add     sp, sp, #8                  @ restore stack
   10190     bmi     .LnotCaughtLocally
   10191 
   10192     /* adjust locals to match self->curFrame and updated PC */
   10193     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
   10194     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
   10195     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
   10196     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
   10197     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
   10198     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
   10199     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
   10200     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
   10201 
   10202     /* release the tracked alloc on the exception */
   10203     mov     r0, r9                      @ r0<- exception
   10204     mov     r1, r10                     @ r1<- self
   10205     bl      dvmReleaseTrackedAlloc      @ release the exception
   10206 
   10207     /* restore the exception if the handler wants it */
   10208     FETCH_INST()                        @ load rINST from rPC
   10209     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10210     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
   10211     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
   10212     GOTO_OPCODE(ip)                     @ jump to next instruction
   10213 
   10214 .LnotCaughtLocally: @ r9=exception, r10=self
   10215     /* fix stack overflow if necessary */
   10216     ldrb    r1, [r10, #offThread_stackOverflowed]
   10217     cmp     r1, #0                      @ did we overflow earlier?
   10218     movne   r0, r10                     @ if yes: r0<- self
   10219     movne   r1, r9                      @ if yes: r1<- exception
   10220     blne    dvmCleanupStackOverflow     @ if yes: call(self)
   10221 
   10222     @ may want to show "not caught locally" debug messages here
   10223 #if DVM_SHOW_EXCEPTION >= 2
   10224     /* call __android_log_print(prio, tag, format, ...) */
   10225     /* "Exception %s from %s:%d not caught locally" */
   10226     @ dvmLineNumFromPC(method, pc - method->insns)
   10227     ldr     r0, [rGLUE, #offGlue_method]
   10228     ldr     r1, [r0, #offMethod_insns]
   10229     sub     r1, rPC, r1
   10230     asr     r1, r1, #1
   10231     bl      dvmLineNumFromPC
   10232     str     r0, [sp, #-4]!
   10233     @ dvmGetMethodSourceFile(method)
   10234     ldr     r0, [rGLUE, #offGlue_method]
   10235     bl      dvmGetMethodSourceFile
   10236     str     r0, [sp, #-4]!
   10237     @ exception->clazz->descriptor
   10238     ldr     r3, [r9, #offObject_clazz]
   10239     ldr     r3, [r3, #offClassObject_descriptor]
   10240     @
   10241     ldr     r2, strExceptionNotCaughtLocally
   10242     ldr     r1, strLogTag
   10243     mov     r0, #3                      @ LOG_DEBUG
   10244     bl      __android_log_print
   10245 #endif
   10246     str     r9, [r10, #offThread_exception] @ restore exception
   10247     mov     r0, r9                      @ r0<- exception
   10248     mov     r1, r10                     @ r1<- self
   10249     bl      dvmReleaseTrackedAlloc      @ release the exception
   10250     mov     r1, #0                      @ "want switch" = false
   10251     b       common_gotoBail             @ bail out
   10252 
   10253 
   10254     /*
   10255      * Exception handling, calls through "glue code".
   10256      */
   10257     .if     0
   10258 .LexceptionOld:
   10259     SAVE_PC_FP_TO_GLUE()                @ export state
   10260     mov     r0, rGLUE                   @ arg to function
   10261     bl      dvmMterp_exceptionThrown
   10262     b       common_resumeAfterGlueCall
   10263     .endif
   10264 
   10265 
   10266 /*
   10267  * After returning from a "glued" function, pull out the updated
   10268  * values and start executing at the next instruction.
   10269  */
   10270 common_resumeAfterGlueCall:
   10271     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
   10272     FETCH_INST()                        @ load rINST from rPC
   10273     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10274     GOTO_OPCODE(ip)                     @ jump to next instruction
   10275 
   10276 /*
   10277  * Invalid array index.
   10278  */
   10279 common_errArrayIndex:
   10280     EXPORT_PC()
   10281     ldr     r0, strArrayIndexException
   10282     mov     r1, #0
   10283     bl      dvmThrowException
   10284     b       common_exceptionThrown
   10285 
   10286 /*
   10287  * Invalid array value.
   10288  */
   10289 common_errArrayStore:
   10290     EXPORT_PC()
   10291     ldr     r0, strArrayStoreException
   10292     mov     r1, #0
   10293     bl      dvmThrowException
   10294     b       common_exceptionThrown
   10295 
   10296 /*
   10297  * Integer divide or mod by zero.
   10298  */
   10299 common_errDivideByZero:
   10300     EXPORT_PC()
   10301     ldr     r0, strArithmeticException
   10302     ldr     r1, strDivideByZero
   10303     bl      dvmThrowException
   10304     b       common_exceptionThrown
   10305 
   10306 /*
   10307  * Attempt to allocate an array with a negative size.
   10308  */
   10309 common_errNegativeArraySize:
   10310     EXPORT_PC()
   10311     ldr     r0, strNegativeArraySizeException
   10312     mov     r1, #0
   10313     bl      dvmThrowException
   10314     b       common_exceptionThrown
   10315 
   10316 /*
   10317  * Invocation of a non-existent method.
   10318  */
   10319 common_errNoSuchMethod:
   10320     EXPORT_PC()
   10321     ldr     r0, strNoSuchMethodError
   10322     mov     r1, #0
   10323     bl      dvmThrowException
   10324     b       common_exceptionThrown
   10325 
   10326 /*
   10327  * We encountered a null object when we weren't expecting one.  We
   10328  * export the PC, throw a NullPointerException, and goto the exception
   10329  * processing code.
   10330  */
   10331 common_errNullObject:
   10332     EXPORT_PC()
   10333     ldr     r0, strNullPointerException
   10334     mov     r1, #0
   10335     bl      dvmThrowException
   10336     b       common_exceptionThrown
   10337 
   10338 /*
   10339  * For debugging, cause an immediate fault.  The source address will
   10340  * be in lr (use a bl instruction to jump here).
   10341  */
   10342 common_abort:
   10343     ldr     pc, .LdeadFood
   10344 .LdeadFood:
   10345     .word   0xdeadf00d
   10346 
   10347 /*
   10348  * Spit out a "we were here", preserving all registers.  (The attempt
   10349  * to save ip won't work, but we need to save an even number of
   10350  * registers for EABI 64-bit stack alignment.)
   10351  */
   10352     .macro  SQUEAK num
   10353 common_squeak\num:
   10354     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10355     ldr     r0, strSqueak
   10356     mov     r1, #\num
   10357     bl      printf
   10358     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10359     bx      lr
   10360     .endm
   10361 
   10362     SQUEAK  0
   10363     SQUEAK  1
   10364     SQUEAK  2
   10365     SQUEAK  3
   10366     SQUEAK  4
   10367     SQUEAK  5
   10368 
   10369 /*
   10370  * Spit out the number in r0, preserving registers.
   10371  */
   10372 common_printNum:
   10373     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10374     mov     r1, r0
   10375     ldr     r0, strSqueak
   10376     bl      printf
   10377     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10378     bx      lr
   10379 
   10380 /*
   10381  * Print a newline, preserving registers.
   10382  */
   10383 common_printNewline:
   10384     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10385     ldr     r0, strNewline
   10386     bl      printf
   10387     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10388     bx      lr
   10389 
   10390     /*
   10391      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
   10392      */
   10393 common_printHex:
   10394     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10395     mov     r1, r0
   10396     ldr     r0, strPrintHex
   10397     bl      printf
   10398     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10399     bx      lr
   10400 
   10401 /*
   10402  * Print the 64-bit quantity in r0-r1, preserving registers.
   10403  */
   10404 common_printLong:
   10405     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10406     mov     r3, r1
   10407     mov     r2, r0
   10408     ldr     r0, strPrintLong
   10409     bl      printf
   10410     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10411     bx      lr
   10412 
   10413 /*
   10414  * Print full method info.  Pass the Method* in r0.  Preserves regs.
   10415  */
   10416 common_printMethod:
   10417     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10418     bl      dvmMterpPrintMethod
   10419     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10420     bx      lr
   10421 
   10422 /*
   10423  * Call a C helper function that dumps regs and possibly some
   10424  * additional info.  Requires the C function to be compiled in.
   10425  */
   10426     .if     0
   10427 common_dumpRegs:
   10428     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10429     bl      dvmMterpDumpArmRegs
   10430     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10431     bx      lr
   10432     .endif
   10433 
   10434 #if 0
   10435 /*
   10436  * Experiment on VFP mode.
   10437  *
   10438  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
   10439  *
   10440  * Updates the bits specified by "mask", setting them to the values in "val".
   10441  */
   10442 setFPSCR:
   10443     and     r0, r0, r1                  @ make sure no stray bits are set
   10444     fmrx    r2, fpscr                   @ get VFP reg
   10445     mvn     r1, r1                      @ bit-invert mask
   10446     and     r2, r2, r1                  @ clear masked bits
   10447     orr     r2, r2, r0                  @ set specified bits
   10448     fmxr    fpscr, r2                   @ set VFP reg
   10449     mov     r0, r2                      @ return new value
   10450     bx      lr
   10451 
   10452     .align  2
   10453     .global dvmConfigureFP
   10454     .type   dvmConfigureFP, %function
   10455 dvmConfigureFP:
   10456     stmfd   sp!, {ip, lr}
   10457     /* 0x03000000 sets DN/FZ */
   10458     /* 0x00009f00 clears the six exception enable flags */
   10459     bl      common_squeak0
   10460     mov     r0, #0x03000000             @ r0<- 0x03000000
   10461     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
   10462     bl      setFPSCR
   10463     ldmfd   sp!, {ip, pc}
   10464 #endif
   10465 
   10466 
   10467 /*
   10468  * String references, must be close to the code that uses them.
   10469  */
   10470     .align  2
   10471 strArithmeticException:
   10472     .word   .LstrArithmeticException
   10473 strArrayIndexException:
   10474     .word   .LstrArrayIndexException
   10475 strArrayStoreException:
   10476     .word   .LstrArrayStoreException
   10477 strDivideByZero:
   10478     .word   .LstrDivideByZero
   10479 strNegativeArraySizeException:
   10480     .word   .LstrNegativeArraySizeException
   10481 strNoSuchMethodError:
   10482     .word   .LstrNoSuchMethodError
   10483 strNullPointerException:
   10484     .word   .LstrNullPointerException
   10485 
   10486 strLogTag:
   10487     .word   .LstrLogTag
   10488 strExceptionNotCaughtLocally:
   10489     .word   .LstrExceptionNotCaughtLocally
   10490 
   10491 strNewline:
   10492     .word   .LstrNewline
   10493 strSqueak:
   10494     .word   .LstrSqueak
   10495 strPrintHex:
   10496     .word   .LstrPrintHex
   10497 strPrintLong:
   10498     .word   .LstrPrintLong
   10499 
   10500 /*
   10501  * Zero-terminated ASCII string data.
   10502  *
   10503  * On ARM we have two choices: do like gcc does, and LDR from a .word
   10504  * with the address, or use an ADR pseudo-op to get the address
   10505  * directly.  ADR saves 4 bytes and an indirection, but it's using a
   10506  * PC-relative addressing mode and hence has a limited range, which
   10507  * makes it not work well with mergeable string sections.
   10508  */
   10509     .section .rodata.str1.4,"aMS",%progbits,1
   10510 
   10511 .LstrBadEntryPoint:
   10512     .asciz  "Bad entry point %d\n"
   10513 .LstrArithmeticException:
   10514     .asciz  "Ljava/lang/ArithmeticException;"
   10515 .LstrArrayIndexException:
   10516     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
   10517 .LstrArrayStoreException:
   10518     .asciz  "Ljava/lang/ArrayStoreException;"
   10519 .LstrClassCastException:
   10520     .asciz  "Ljava/lang/ClassCastException;"
   10521 .LstrDivideByZero:
   10522     .asciz  "divide by zero"
   10523 .LstrFilledNewArrayNotImpl:
   10524     .asciz  "filled-new-array only implemented for objects and 'int'"
   10525 .LstrInternalError:
   10526     .asciz  "Ljava/lang/InternalError;"
   10527 .LstrInstantiationError:
   10528     .asciz  "Ljava/lang/InstantiationError;"
   10529 .LstrNegativeArraySizeException:
   10530     .asciz  "Ljava/lang/NegativeArraySizeException;"
   10531 .LstrNoSuchMethodError:
   10532     .asciz  "Ljava/lang/NoSuchMethodError;"
   10533 .LstrNullPointerException:
   10534     .asciz  "Ljava/lang/NullPointerException;"
   10535 
   10536 .LstrLogTag:
   10537     .asciz  "mterp"
   10538 .LstrExceptionNotCaughtLocally:
   10539     .asciz  "Exception %s from %s:%d not caught locally\n"
   10540 
   10541 .LstrNewline:
   10542     .asciz  "\n"
   10543 .LstrSqueak:
   10544     .asciz  "<%d>"
   10545 .LstrPrintHex:
   10546     .asciz  "<0x%x>"
   10547 .LstrPrintLong:
   10548     .asciz  "<%lld>"
   10549 
   10550