Home | History | Annotate | Download | only in out
      1 /*
      2  * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
      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: armv5te/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 /*
    247  * Macro for data memory barrier; not meaningful pre-ARMv6K.
    248  */
    249 .macro  SMP_DMB
    250 .endm
    251 
    252 /* File: armv5te/entry.S */
    253 /*
    254  * Copyright (C) 2008 The Android Open Source Project
    255  *
    256  * Licensed under the Apache License, Version 2.0 (the "License");
    257  * you may not use this file except in compliance with the License.
    258  * You may obtain a copy of the License at
    259  *
    260  *      http://www.apache.org/licenses/LICENSE-2.0
    261  *
    262  * Unless required by applicable law or agreed to in writing, software
    263  * distributed under the License is distributed on an "AS IS" BASIS,
    264  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    265  * See the License for the specific language governing permissions and
    266  * limitations under the License.
    267  */
    268 /*
    269  * Interpreter entry point.
    270  */
    271 
    272 /*
    273  * We don't have formal stack frames, so gdb scans upward in the code
    274  * to find the start of the function (a label with the %function type),
    275  * and then looks at the next few instructions to figure out what
    276  * got pushed onto the stack.  From this it figures out how to restore
    277  * the registers, including PC, for the previous stack frame.  If gdb
    278  * sees a non-function label, it stops scanning, so either we need to
    279  * have nothing but assembler-local labels between the entry point and
    280  * the break, or we need to fake it out.
    281  *
    282  * When this is defined, we add some stuff to make gdb less confused.
    283  */
    284 #define ASSIST_DEBUGGER 1
    285 
    286     .text
    287     .align  2
    288     .global dvmMterpStdRun
    289     .type   dvmMterpStdRun, %function
    290 
    291 /*
    292  * On entry:
    293  *  r0  MterpGlue* glue
    294  *
    295  * This function returns a boolean "changeInterp" value.  The return comes
    296  * via a call to dvmMterpStdBail().
    297  */
    298 dvmMterpStdRun:
    299 #define MTERP_ENTRY1 \
    300     .save {r4-r10,fp,lr}; \
    301     stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
    302 #define MTERP_ENTRY2 \
    303     .pad    #4; \
    304     sub     sp, sp, #4                  @ align 64
    305 
    306     .fnstart
    307     MTERP_ENTRY1
    308     MTERP_ENTRY2
    309 
    310     /* save stack pointer, add magic word for debuggerd */
    311     str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
    312 
    313     /* set up "named" registers, figure out entry point */
    314     mov     rGLUE, r0                   @ set rGLUE
    315     ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
    316     LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
    317     adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
    318     cmp     r1, #kInterpEntryInstr      @ usual case?
    319     bne     .Lnot_instr                 @ no, handle it
    320 
    321 #if defined(WITH_JIT)
    322 .LentryInstr:
    323     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
    324     /* Entry is always a possible trace start */
    325     GET_JIT_PROF_TABLE(r0)
    326     FETCH_INST()
    327     mov     r1, #0                      @ prepare the value for the new state
    328     str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
    329     cmp     r0,#0                       @ is profiling disabled?
    330 #if !defined(WITH_SELF_VERIFICATION)
    331     bne     common_updateProfile        @ profiling is enabled
    332 #else
    333     ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
    334     beq     1f                          @ profiling is disabled
    335     ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
    336     cmp     r3, #kSVSTraceSelect        @ hot trace following?
    337     moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
    338     beq     common_selectTrace          @ go build the trace
    339     cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
    340     beq     1f                          @ intrepret the next instruction
    341     b       common_updateProfile        @ collect profiles
    342 #endif
    343 1:
    344     GET_INST_OPCODE(ip)
    345     GOTO_OPCODE(ip)
    346 #else
    347     /* start executing the instruction at rPC */
    348     FETCH_INST()                        @ load rINST from rPC
    349     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    350     GOTO_OPCODE(ip)                     @ jump to next instruction
    351 #endif
    352 
    353 .Lnot_instr:
    354     cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
    355     beq     common_returnFromMethod
    356 
    357 .Lnot_return:
    358     cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
    359     beq     common_exceptionThrown
    360 
    361 #if defined(WITH_JIT)
    362 .Lnot_throw:
    363     ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
    364     ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
    365     cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
    366     bne     .Lbad_arg
    367     cmp     rPC,r2
    368     bne     .LentryInstr                @ must have branched, don't resume
    369 #if defined(WITH_SELF_VERIFICATION)
    370     @ glue->entryPoint will be set in dvmSelfVerificationSaveState
    371     b       jitSVShadowRunStart         @ re-enter the translation after the
    372                                         @ single-stepped instruction
    373     @noreturn
    374 #endif
    375     mov     r1, #kInterpEntryInstr
    376     str     r1, [rGLUE, #offGlue_entryPoint]
    377     bx      r10                         @ re-enter the translation
    378 #endif
    379 
    380 .Lbad_arg:
    381     ldr     r0, strBadEntryPoint
    382     @ r1 holds value of entryPoint
    383     bl      printf
    384     bl      dvmAbort
    385     .fnend
    386 
    387 
    388     .global dvmMterpStdBail
    389     .type   dvmMterpStdBail, %function
    390 
    391 /*
    392  * Restore the stack pointer and PC from the save point established on entry.
    393  * This is essentially the same as a longjmp, but should be cheaper.  The
    394  * last instruction causes us to return to whoever called dvmMterpStdRun.
    395  *
    396  * We pushed some registers on the stack in dvmMterpStdRun, then saved
    397  * SP and LR.  Here we restore SP, restore the registers, and then restore
    398  * LR to PC.
    399  *
    400  * On entry:
    401  *  r0  MterpGlue* glue
    402  *  r1  bool changeInterp
    403  */
    404 dvmMterpStdBail:
    405     ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
    406     mov     r0, r1                          @ return the changeInterp value
    407     add     sp, sp, #4                      @ un-align 64
    408     LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
    409 
    410 
    411 /*
    412  * String references.
    413  */
    414 strBadEntryPoint:
    415     .word   .LstrBadEntryPoint
    416 
    417 
    418     .global dvmAsmInstructionStart
    419     .type   dvmAsmInstructionStart, %function
    420 dvmAsmInstructionStart = .L_OP_NOP
    421     .text
    422 
    423 /* ------------------------------ */
    424     .balign 64
    425 .L_OP_NOP: /* 0x00 */
    426 /* File: armv5te/OP_NOP.S */
    427     FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
    428     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    429     GOTO_OPCODE(ip)                     @ execute it
    430 
    431 #ifdef ASSIST_DEBUGGER
    432     /* insert fake function header to help gdb find the stack frame */
    433     .type   dalvik_inst, %function
    434 dalvik_inst:
    435     .fnstart
    436     MTERP_ENTRY1
    437     MTERP_ENTRY2
    438     .fnend
    439 #endif
    440 
    441 /* ------------------------------ */
    442     .balign 64
    443 .L_OP_MOVE: /* 0x01 */
    444 /* File: armv5te/OP_MOVE.S */
    445     /* for move, move-object, long-to-int */
    446     /* op vA, vB */
    447     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
    448     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
    449     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    450     GET_VREG(r2, r1)                    @ r2<- fp[B]
    451     and     r0, r0, #15
    452     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    453     SET_VREG(r2, r0)                    @ fp[A]<- r2
    454     GOTO_OPCODE(ip)                     @ execute next instruction
    455 
    456 /* ------------------------------ */
    457     .balign 64
    458 .L_OP_MOVE_FROM16: /* 0x02 */
    459 /* File: armv5te/OP_MOVE_FROM16.S */
    460     /* for: move/from16, move-object/from16 */
    461     /* op vAA, vBBBB */
    462     FETCH(r1, 1)                        @ r1<- BBBB
    463     mov     r0, rINST, lsr #8           @ r0<- AA
    464     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    465     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    466     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    467     SET_VREG(r2, r0)                    @ fp[AA]<- r2
    468     GOTO_OPCODE(ip)                     @ jump to next instruction
    469 
    470 /* ------------------------------ */
    471     .balign 64
    472 .L_OP_MOVE_16: /* 0x03 */
    473 /* File: armv5te/OP_MOVE_16.S */
    474     /* for: move/16, move-object/16 */
    475     /* op vAAAA, vBBBB */
    476     FETCH(r1, 2)                        @ r1<- BBBB
    477     FETCH(r0, 1)                        @ r0<- AAAA
    478     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    479     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    480     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    481     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
    482     GOTO_OPCODE(ip)                     @ jump to next instruction
    483 
    484 /* ------------------------------ */
    485     .balign 64
    486 .L_OP_MOVE_WIDE: /* 0x04 */
    487 /* File: armv5te/OP_MOVE_WIDE.S */
    488     /* move-wide vA, vB */
    489     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    490     mov     r2, rINST, lsr #8           @ r2<- A(+)
    491     mov     r3, rINST, lsr #12          @ r3<- B
    492     and     r2, r2, #15
    493     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
    494     add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
    495     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
    496     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    497     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    498     stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
    499     GOTO_OPCODE(ip)                     @ jump to next instruction
    500 
    501 /* ------------------------------ */
    502     .balign 64
    503 .L_OP_MOVE_WIDE_FROM16: /* 0x05 */
    504 /* File: armv5te/OP_MOVE_WIDE_FROM16.S */
    505     /* move-wide/from16 vAA, vBBBB */
    506     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    507     FETCH(r3, 1)                        @ r3<- BBBB
    508     mov     r2, rINST, lsr #8           @ r2<- AA
    509     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
    510     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
    511     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
    512     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    513     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    514     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
    515     GOTO_OPCODE(ip)                     @ jump to next instruction
    516 
    517 /* ------------------------------ */
    518     .balign 64
    519 .L_OP_MOVE_WIDE_16: /* 0x06 */
    520 /* File: armv5te/OP_MOVE_WIDE_16.S */
    521     /* move-wide/16 vAAAA, vBBBB */
    522     /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
    523     FETCH(r3, 2)                        @ r3<- BBBB
    524     FETCH(r2, 1)                        @ r2<- AAAA
    525     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
    526     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
    527     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
    528     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    529     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    530     stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
    531     GOTO_OPCODE(ip)                     @ jump to next instruction
    532 
    533 /* ------------------------------ */
    534     .balign 64
    535 .L_OP_MOVE_OBJECT: /* 0x07 */
    536 /* File: armv5te/OP_MOVE_OBJECT.S */
    537 /* File: armv5te/OP_MOVE.S */
    538     /* for move, move-object, long-to-int */
    539     /* op vA, vB */
    540     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
    541     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
    542     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    543     GET_VREG(r2, r1)                    @ r2<- fp[B]
    544     and     r0, r0, #15
    545     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    546     SET_VREG(r2, r0)                    @ fp[A]<- r2
    547     GOTO_OPCODE(ip)                     @ execute next instruction
    548 
    549 
    550 /* ------------------------------ */
    551     .balign 64
    552 .L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
    553 /* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
    554 /* File: armv5te/OP_MOVE_FROM16.S */
    555     /* for: move/from16, move-object/from16 */
    556     /* op vAA, vBBBB */
    557     FETCH(r1, 1)                        @ r1<- BBBB
    558     mov     r0, rINST, lsr #8           @ r0<- AA
    559     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    560     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    561     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    562     SET_VREG(r2, r0)                    @ fp[AA]<- r2
    563     GOTO_OPCODE(ip)                     @ jump to next instruction
    564 
    565 
    566 /* ------------------------------ */
    567     .balign 64
    568 .L_OP_MOVE_OBJECT_16: /* 0x09 */
    569 /* File: armv5te/OP_MOVE_OBJECT_16.S */
    570 /* File: armv5te/OP_MOVE_16.S */
    571     /* for: move/16, move-object/16 */
    572     /* op vAAAA, vBBBB */
    573     FETCH(r1, 2)                        @ r1<- BBBB
    574     FETCH(r0, 1)                        @ r0<- AAAA
    575     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    576     GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
    577     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    578     SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
    579     GOTO_OPCODE(ip)                     @ jump to next instruction
    580 
    581 
    582 /* ------------------------------ */
    583     .balign 64
    584 .L_OP_MOVE_RESULT: /* 0x0a */
    585 /* File: armv5te/OP_MOVE_RESULT.S */
    586     /* for: move-result, move-result-object */
    587     /* op vAA */
    588     mov     r2, rINST, lsr #8           @ r2<- AA
    589     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    590     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
    591     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    592     SET_VREG(r0, r2)                    @ fp[AA]<- r0
    593     GOTO_OPCODE(ip)                     @ jump to next instruction
    594 
    595 /* ------------------------------ */
    596     .balign 64
    597 .L_OP_MOVE_RESULT_WIDE: /* 0x0b */
    598 /* File: armv5te/OP_MOVE_RESULT_WIDE.S */
    599     /* move-result-wide vAA */
    600     mov     r2, rINST, lsr #8           @ r2<- AA
    601     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
    602     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
    603     ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
    604     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    605     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    606     stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
    607     GOTO_OPCODE(ip)                     @ jump to next instruction
    608 
    609 /* ------------------------------ */
    610     .balign 64
    611 .L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
    612 /* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
    613 /* File: armv5te/OP_MOVE_RESULT.S */
    614     /* for: move-result, move-result-object */
    615     /* op vAA */
    616     mov     r2, rINST, lsr #8           @ r2<- AA
    617     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    618     ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
    619     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    620     SET_VREG(r0, r2)                    @ fp[AA]<- r0
    621     GOTO_OPCODE(ip)                     @ jump to next instruction
    622 
    623 
    624 /* ------------------------------ */
    625     .balign 64
    626 .L_OP_MOVE_EXCEPTION: /* 0x0d */
    627 /* File: armv5te/OP_MOVE_EXCEPTION.S */
    628     /* move-exception vAA */
    629     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    630     mov     r2, rINST, lsr #8           @ r2<- AA
    631     ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
    632     mov     r1, #0                      @ r1<- 0
    633     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    634     SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
    635     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    636     str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
    637     GOTO_OPCODE(ip)                     @ jump to next instruction
    638 
    639 /* ------------------------------ */
    640     .balign 64
    641 .L_OP_RETURN_VOID: /* 0x0e */
    642 /* File: armv5te/OP_RETURN_VOID.S */
    643     b       common_returnFromMethod
    644 
    645 /* ------------------------------ */
    646     .balign 64
    647 .L_OP_RETURN: /* 0x0f */
    648 /* File: armv5te/OP_RETURN.S */
    649     /*
    650      * Return a 32-bit value.  Copies the return value into the "glue"
    651      * structure, then jumps to the return handler.
    652      *
    653      * for: return, return-object
    654      */
    655     /* op vAA */
    656     mov     r2, rINST, lsr #8           @ r2<- AA
    657     GET_VREG(r0, r2)                    @ r0<- vAA
    658     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
    659     b       common_returnFromMethod
    660 
    661 /* ------------------------------ */
    662     .balign 64
    663 .L_OP_RETURN_WIDE: /* 0x10 */
    664 /* File: armv5te/OP_RETURN_WIDE.S */
    665     /*
    666      * Return a 64-bit value.  Copies the return value into the "glue"
    667      * structure, then jumps to the return handler.
    668      */
    669     /* return-wide vAA */
    670     mov     r2, rINST, lsr #8           @ r2<- AA
    671     add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
    672     add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
    673     ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
    674     stmia   r3, {r0-r1}                 @ retval<- r0/r1
    675     b       common_returnFromMethod
    676 
    677 /* ------------------------------ */
    678     .balign 64
    679 .L_OP_RETURN_OBJECT: /* 0x11 */
    680 /* File: armv5te/OP_RETURN_OBJECT.S */
    681 /* File: armv5te/OP_RETURN.S */
    682     /*
    683      * Return a 32-bit value.  Copies the return value into the "glue"
    684      * structure, then jumps to the return handler.
    685      *
    686      * for: return, return-object
    687      */
    688     /* op vAA */
    689     mov     r2, rINST, lsr #8           @ r2<- AA
    690     GET_VREG(r0, r2)                    @ r0<- vAA
    691     str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
    692     b       common_returnFromMethod
    693 
    694 
    695 /* ------------------------------ */
    696     .balign 64
    697 .L_OP_CONST_4: /* 0x12 */
    698 /* File: armv5te/OP_CONST_4.S */
    699     /* const/4 vA, #+B */
    700     mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
    701     mov     r0, rINST, lsr #8           @ r0<- A+
    702     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    703     mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
    704     and     r0, r0, #15
    705     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
    706     SET_VREG(r1, r0)                    @ fp[A]<- r1
    707     GOTO_OPCODE(ip)                     @ execute next instruction
    708 
    709 /* ------------------------------ */
    710     .balign 64
    711 .L_OP_CONST_16: /* 0x13 */
    712 /* File: armv5te/OP_CONST_16.S */
    713     /* const/16 vAA, #+BBBB */
    714     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
    715     mov     r3, rINST, lsr #8           @ r3<- AA
    716     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    717     SET_VREG(r0, r3)                    @ vAA<- r0
    718     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    719     GOTO_OPCODE(ip)                     @ jump to next instruction
    720 
    721 /* ------------------------------ */
    722     .balign 64
    723 .L_OP_CONST: /* 0x14 */
    724 /* File: armv5te/OP_CONST.S */
    725     /* const vAA, #+BBBBbbbb */
    726     mov     r3, rINST, lsr #8           @ r3<- AA
    727     FETCH(r0, 1)                        @ r0<- bbbb (low)
    728     FETCH(r1, 2)                        @ r1<- BBBB (high)
    729     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    730     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
    731     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    732     SET_VREG(r0, r3)                    @ vAA<- r0
    733     GOTO_OPCODE(ip)                     @ jump to next instruction
    734 
    735 /* ------------------------------ */
    736     .balign 64
    737 .L_OP_CONST_HIGH16: /* 0x15 */
    738 /* File: armv5te/OP_CONST_HIGH16.S */
    739     /* const/high16 vAA, #+BBBB0000 */
    740     FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
    741     mov     r3, rINST, lsr #8           @ r3<- AA
    742     mov     r0, r0, lsl #16             @ r0<- BBBB0000
    743     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    744     SET_VREG(r0, r3)                    @ vAA<- r0
    745     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    746     GOTO_OPCODE(ip)                     @ jump to next instruction
    747 
    748 /* ------------------------------ */
    749     .balign 64
    750 .L_OP_CONST_WIDE_16: /* 0x16 */
    751 /* File: armv5te/OP_CONST_WIDE_16.S */
    752     /* const-wide/16 vAA, #+BBBB */
    753     FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
    754     mov     r3, rINST, lsr #8           @ r3<- AA
    755     mov     r1, r0, asr #31             @ r1<- ssssssss
    756     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    757     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
    758     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    759     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
    760     GOTO_OPCODE(ip)                     @ jump to next instruction
    761 
    762 /* ------------------------------ */
    763     .balign 64
    764 .L_OP_CONST_WIDE_32: /* 0x17 */
    765 /* File: armv5te/OP_CONST_WIDE_32.S */
    766     /* const-wide/32 vAA, #+BBBBbbbb */
    767     FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
    768     mov     r3, rINST, lsr #8           @ r3<- AA
    769     FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
    770     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    771     orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
    772     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
    773     mov     r1, r0, asr #31             @ r1<- ssssssss
    774     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    775     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
    776     GOTO_OPCODE(ip)                     @ jump to next instruction
    777 
    778 /* ------------------------------ */
    779     .balign 64
    780 .L_OP_CONST_WIDE: /* 0x18 */
    781 /* File: armv5te/OP_CONST_WIDE.S */
    782     /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
    783     FETCH(r0, 1)                        @ r0<- bbbb (low)
    784     FETCH(r1, 2)                        @ r1<- BBBB (low middle)
    785     FETCH(r2, 3)                        @ r2<- hhhh (high middle)
    786     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
    787     FETCH(r3, 4)                        @ r3<- HHHH (high)
    788     mov     r9, rINST, lsr #8           @ r9<- AA
    789     orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
    790     FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
    791     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
    792     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    793     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
    794     GOTO_OPCODE(ip)                     @ jump to next instruction
    795 
    796 /* ------------------------------ */
    797     .balign 64
    798 .L_OP_CONST_WIDE_HIGH16: /* 0x19 */
    799 /* File: armv5te/OP_CONST_WIDE_HIGH16.S */
    800     /* const-wide/high16 vAA, #+BBBB000000000000 */
    801     FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
    802     mov     r3, rINST, lsr #8           @ r3<- AA
    803     mov     r0, #0                      @ r0<- 00000000
    804     mov     r1, r1, lsl #16             @ r1<- BBBB0000
    805     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    806     add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
    807     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    808     stmia   r3, {r0-r1}                 @ vAA<- r0/r1
    809     GOTO_OPCODE(ip)                     @ jump to next instruction
    810 
    811 /* ------------------------------ */
    812     .balign 64
    813 .L_OP_CONST_STRING: /* 0x1a */
    814 /* File: armv5te/OP_CONST_STRING.S */
    815     /* const/string vAA, String@BBBB */
    816     FETCH(r1, 1)                        @ r1<- BBBB
    817     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
    818     mov     r9, rINST, lsr #8           @ r9<- AA
    819     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
    820     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
    821     cmp     r0, #0                      @ not yet resolved?
    822     beq     .LOP_CONST_STRING_resolve
    823     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    824     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    825     SET_VREG(r0, r9)                    @ vAA<- r0
    826     GOTO_OPCODE(ip)                     @ jump to next instruction
    827 
    828 /* ------------------------------ */
    829     .balign 64
    830 .L_OP_CONST_STRING_JUMBO: /* 0x1b */
    831 /* File: armv5te/OP_CONST_STRING_JUMBO.S */
    832     /* const/string vAA, String@BBBBBBBB */
    833     FETCH(r0, 1)                        @ r0<- bbbb (low)
    834     FETCH(r1, 2)                        @ r1<- BBBB (high)
    835     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
    836     mov     r9, rINST, lsr #8           @ r9<- AA
    837     ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
    838     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
    839     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
    840     cmp     r0, #0
    841     beq     .LOP_CONST_STRING_JUMBO_resolve
    842     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
    843     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    844     SET_VREG(r0, r9)                    @ vAA<- r0
    845     GOTO_OPCODE(ip)                     @ jump to next instruction
    846 
    847 /* ------------------------------ */
    848     .balign 64
    849 .L_OP_CONST_CLASS: /* 0x1c */
    850 /* File: armv5te/OP_CONST_CLASS.S */
    851     /* const/class vAA, Class@BBBB */
    852     FETCH(r1, 1)                        @ r1<- BBBB
    853     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
    854     mov     r9, rINST, lsr #8           @ r9<- AA
    855     ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
    856     ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
    857     cmp     r0, #0                      @ not yet resolved?
    858     beq     .LOP_CONST_CLASS_resolve
    859     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    860     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    861     SET_VREG(r0, r9)                    @ vAA<- r0
    862     GOTO_OPCODE(ip)                     @ jump to next instruction
    863 
    864 /* ------------------------------ */
    865     .balign 64
    866 .L_OP_MONITOR_ENTER: /* 0x1d */
    867 /* File: armv5te/OP_MONITOR_ENTER.S */
    868     /*
    869      * Synchronize on an object.
    870      */
    871     /* monitor-enter vAA */
    872     mov     r2, rINST, lsr #8           @ r2<- AA
    873     GET_VREG(r1, r2)                    @ r1<- vAA (object)
    874     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    875     cmp     r1, #0                      @ null object?
    876     EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
    877     beq     common_errNullObject        @ null object, throw an exception
    878     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    879     bl      dvmLockObject               @ call(self, obj)
    880 #ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
    881     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    882     ldr     r1, [r0, #offThread_exception] @ check for exception
    883     cmp     r1, #0
    884     bne     common_exceptionThrown      @ exception raised, bail out
    885 #endif
    886     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    887     GOTO_OPCODE(ip)                     @ jump to next instruction
    888 
    889 /* ------------------------------ */
    890     .balign 64
    891 .L_OP_MONITOR_EXIT: /* 0x1e */
    892 /* File: armv5te/OP_MONITOR_EXIT.S */
    893     /*
    894      * Unlock an object.
    895      *
    896      * Exceptions that occur when unlocking a monitor need to appear as
    897      * if they happened at the following instruction.  See the Dalvik
    898      * instruction spec.
    899      */
    900     /* monitor-exit vAA */
    901     mov     r2, rINST, lsr #8           @ r2<- AA
    902     EXPORT_PC()                         @ before fetch: export the PC
    903     GET_VREG(r1, r2)                    @ r1<- vAA (object)
    904     cmp     r1, #0                      @ null object?
    905     beq     1f                          @ yes
    906     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
    907     bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
    908     cmp     r0, #0                      @ failed?
    909     FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
    910     beq     common_exceptionThrown      @ yes, exception is pending
    911     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    912     GOTO_OPCODE(ip)                     @ jump to next instruction
    913 1:
    914     FETCH_ADVANCE_INST(1)               @ advance before throw
    915     b      common_errNullObject
    916 
    917 /* ------------------------------ */
    918     .balign 64
    919 .L_OP_CHECK_CAST: /* 0x1f */
    920 /* File: armv5te/OP_CHECK_CAST.S */
    921     /*
    922      * Check to see if a cast from one class to another is allowed.
    923      */
    924     /* check-cast vAA, class@BBBB */
    925     mov     r3, rINST, lsr #8           @ r3<- AA
    926     FETCH(r2, 1)                        @ r2<- BBBB
    927     GET_VREG(r9, r3)                    @ r9<- object
    928     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
    929     cmp     r9, #0                      @ is object null?
    930     ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
    931     beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
    932     ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
    933     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
    934     cmp     r1, #0                      @ have we resolved this before?
    935     beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
    936 .LOP_CHECK_CAST_resolved:
    937     cmp     r0, r1                      @ same class (trivial success)?
    938     bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
    939 .LOP_CHECK_CAST_okay:
    940     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
    941     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    942     GOTO_OPCODE(ip)                     @ jump to next instruction
    943 
    944 /* ------------------------------ */
    945     .balign 64
    946 .L_OP_INSTANCE_OF: /* 0x20 */
    947 /* File: armv5te/OP_INSTANCE_OF.S */
    948     /*
    949      * Check to see if an object reference is an instance of a class.
    950      *
    951      * Most common situation is a non-null object, being compared against
    952      * an already-resolved class.
    953      */
    954     /* instance-of vA, vB, class@CCCC */
    955     mov     r3, rINST, lsr #12          @ r3<- B
    956     mov     r9, rINST, lsr #8           @ r9<- A+
    957     GET_VREG(r0, r3)                    @ r0<- vB (object)
    958     and     r9, r9, #15                 @ r9<- A
    959     cmp     r0, #0                      @ is object null?
    960     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
    961     beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
    962     FETCH(r3, 1)                        @ r3<- CCCC
    963     ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
    964     ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
    965     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
    966     cmp     r1, #0                      @ have we resolved this before?
    967     beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
    968 .LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
    969     cmp     r0, r1                      @ same class (trivial success)?
    970     beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
    971     b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
    972 
    973 /* ------------------------------ */
    974     .balign 64
    975 .L_OP_ARRAY_LENGTH: /* 0x21 */
    976 /* File: armv5te/OP_ARRAY_LENGTH.S */
    977     /*
    978      * Return the length of an array.
    979      */
    980     mov     r1, rINST, lsr #12          @ r1<- B
    981     mov     r2, rINST, lsr #8           @ r2<- A+
    982     GET_VREG(r0, r1)                    @ r0<- vB (object ref)
    983     and     r2, r2, #15                 @ r2<- A
    984     cmp     r0, #0                      @ is object null?
    985     beq     common_errNullObject        @ yup, fail
    986     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
    987     ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
    988     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
    989     SET_VREG(r3, r2)                    @ vB<- length
    990     GOTO_OPCODE(ip)                     @ jump to next instruction
    991 
    992 /* ------------------------------ */
    993     .balign 64
    994 .L_OP_NEW_INSTANCE: /* 0x22 */
    995 /* File: armv5te/OP_NEW_INSTANCE.S */
    996     /*
    997      * Create a new instance of a class.
    998      */
    999     /* new-instance vAA, class@BBBB */
   1000     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1001     FETCH(r1, 1)                        @ r1<- BBBB
   1002     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1003     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
   1004     EXPORT_PC()                         @ req'd for init, resolve, alloc
   1005     cmp     r0, #0                      @ already resolved?
   1006     beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
   1007 .LOP_NEW_INSTANCE_resolved:   @ r0=class
   1008     ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
   1009     cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
   1010     bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
   1011 .LOP_NEW_INSTANCE_initialized: @ r0=class
   1012     mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
   1013     bl      dvmAllocObject              @ r0<- new object
   1014     b       .LOP_NEW_INSTANCE_finish          @ continue
   1015 
   1016 /* ------------------------------ */
   1017     .balign 64
   1018 .L_OP_NEW_ARRAY: /* 0x23 */
   1019 /* File: armv5te/OP_NEW_ARRAY.S */
   1020     /*
   1021      * Allocate an array of objects, specified with the array class
   1022      * and a count.
   1023      *
   1024      * The verifier guarantees that this is an array class, so we don't
   1025      * check for it here.
   1026      */
   1027     /* new-array vA, vB, class@CCCC */
   1028     mov     r0, rINST, lsr #12          @ r0<- B
   1029     FETCH(r2, 1)                        @ r2<- CCCC
   1030     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1031     GET_VREG(r1, r0)                    @ r1<- vB (array length)
   1032     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1033     cmp     r1, #0                      @ check length
   1034     ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
   1035     bmi     common_errNegativeArraySize @ negative length, bail
   1036     cmp     r0, #0                      @ already resolved?
   1037     EXPORT_PC()                         @ req'd for resolve, alloc
   1038     bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
   1039     b       .LOP_NEW_ARRAY_resolve         @ do resolve now
   1040 
   1041 /* ------------------------------ */
   1042     .balign 64
   1043 .L_OP_FILLED_NEW_ARRAY: /* 0x24 */
   1044 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
   1045     /*
   1046      * Create a new array with elements filled from registers.
   1047      *
   1048      * for: filled-new-array, filled-new-array/range
   1049      */
   1050     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   1051     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
   1052     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1053     FETCH(r1, 1)                        @ r1<- BBBB
   1054     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1055     EXPORT_PC()                         @ need for resolve and alloc
   1056     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
   1057     mov     r10, rINST, lsr #8          @ r10<- AA or BA
   1058     cmp     r0, #0                      @ already resolved?
   1059     bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
   1060 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   1061     mov     r2, #0                      @ r2<- false
   1062     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   1063     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   1064     cmp     r0, #0                      @ got null?
   1065     beq     common_exceptionThrown      @ yes, handle exception
   1066     b       .LOP_FILLED_NEW_ARRAY_continue
   1067 
   1068 /* ------------------------------ */
   1069     .balign 64
   1070 .L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
   1071 /* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
   1072 /* File: armv5te/OP_FILLED_NEW_ARRAY.S */
   1073     /*
   1074      * Create a new array with elements filled from registers.
   1075      *
   1076      * for: filled-new-array, filled-new-array/range
   1077      */
   1078     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   1079     /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
   1080     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   1081     FETCH(r1, 1)                        @ r1<- BBBB
   1082     ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
   1083     EXPORT_PC()                         @ need for resolve and alloc
   1084     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
   1085     mov     r10, rINST, lsr #8          @ r10<- AA or BA
   1086     cmp     r0, #0                      @ already resolved?
   1087     bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
   1088 8:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   1089     mov     r2, #0                      @ r2<- false
   1090     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   1091     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   1092     cmp     r0, #0                      @ got null?
   1093     beq     common_exceptionThrown      @ yes, handle exception
   1094     b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
   1095 
   1096 
   1097 /* ------------------------------ */
   1098     .balign 64
   1099 .L_OP_FILL_ARRAY_DATA: /* 0x26 */
   1100 /* File: armv5te/OP_FILL_ARRAY_DATA.S */
   1101     /* fill-array-data vAA, +BBBBBBBB */
   1102     FETCH(r0, 1)                        @ r0<- bbbb (lo)
   1103     FETCH(r1, 2)                        @ r1<- BBBB (hi)
   1104     mov     r3, rINST, lsr #8           @ r3<- AA
   1105     orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
   1106     GET_VREG(r0, r3)                    @ r0<- vAA (array object)
   1107     add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
   1108     EXPORT_PC();
   1109     bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
   1110     cmp     r0, #0                      @ 0 means an exception is thrown
   1111     beq     common_exceptionThrown      @ has exception
   1112     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   1113     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1114     GOTO_OPCODE(ip)                     @ jump to next instruction
   1115 
   1116 /* ------------------------------ */
   1117     .balign 64
   1118 .L_OP_THROW: /* 0x27 */
   1119 /* File: armv5te/OP_THROW.S */
   1120     /*
   1121      * Throw an exception object in the current thread.
   1122      */
   1123     /* throw vAA */
   1124     mov     r2, rINST, lsr #8           @ r2<- AA
   1125     GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
   1126     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   1127     EXPORT_PC()                         @ exception handler can throw
   1128     cmp     r1, #0                      @ null object?
   1129     beq     common_errNullObject        @ yes, throw an NPE instead
   1130     @ bypass dvmSetException, just store it
   1131     str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
   1132     b       common_exceptionThrown
   1133 
   1134 /* ------------------------------ */
   1135     .balign 64
   1136 .L_OP_GOTO: /* 0x28 */
   1137 /* File: armv5te/OP_GOTO.S */
   1138     /*
   1139      * Unconditional branch, 8-bit offset.
   1140      *
   1141      * The branch distance is a signed code-unit offset, which we need to
   1142      * double to get a byte offset.
   1143      */
   1144     /* goto +AA */
   1145     mov     r0, rINST, lsl #16          @ r0<- AAxx0000
   1146     movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
   1147     mov     r9, r9, lsl #1              @ r9<- byte offset
   1148     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1149 #if defined(WITH_JIT)
   1150     GET_JIT_PROF_TABLE(r0)
   1151     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1152     cmp     r0,#0
   1153     bne     common_updateProfile
   1154     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1155     GOTO_OPCODE(ip)                     @ jump to next instruction
   1156 #else
   1157     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1158     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1159     GOTO_OPCODE(ip)                     @ jump to next instruction
   1160 #endif
   1161 
   1162 /* ------------------------------ */
   1163     .balign 64
   1164 .L_OP_GOTO_16: /* 0x29 */
   1165 /* File: armv5te/OP_GOTO_16.S */
   1166     /*
   1167      * Unconditional branch, 16-bit offset.
   1168      *
   1169      * The branch distance is a signed code-unit offset, which we need to
   1170      * double to get a byte offset.
   1171      */
   1172     /* goto/16 +AAAA */
   1173     FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
   1174     movs    r9, r0, asl #1              @ r9<- byte offset, check sign
   1175     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1176 #if defined(WITH_JIT)
   1177     GET_JIT_PROF_TABLE(r0)
   1178     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1179     cmp     r0,#0
   1180     bne     common_updateProfile
   1181     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1182     GOTO_OPCODE(ip)                     @ jump to next instruction
   1183 #else
   1184     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1185     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1186     GOTO_OPCODE(ip)                     @ jump to next instruction
   1187 #endif
   1188 
   1189 /* ------------------------------ */
   1190     .balign 64
   1191 .L_OP_GOTO_32: /* 0x2a */
   1192 /* File: armv5te/OP_GOTO_32.S */
   1193     /*
   1194      * Unconditional branch, 32-bit offset.
   1195      *
   1196      * The branch distance is a signed code-unit offset, which we need to
   1197      * double to get a byte offset.
   1198      *
   1199      * Unlike most opcodes, this one is allowed to branch to itself, so
   1200      * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
   1201      * instruction doesn't affect the V flag, so we need to clear it
   1202      * explicitly.
   1203      */
   1204     /* goto/32 +AAAAAAAA */
   1205     FETCH(r0, 1)                        @ r0<- aaaa (lo)
   1206     FETCH(r1, 2)                        @ r1<- AAAA (hi)
   1207     cmp     ip, ip                      @ (clear V flag during stall)
   1208     orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
   1209     mov     r9, r0, asl #1              @ r9<- byte offset
   1210     ble     common_backwardBranch       @ backward branch, do periodic checks
   1211 #if defined(WITH_JIT)
   1212     GET_JIT_PROF_TABLE(r0)
   1213     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1214     cmp     r0,#0
   1215     bne     common_updateProfile
   1216     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1217     GOTO_OPCODE(ip)                     @ jump to next instruction
   1218 #else
   1219     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1220     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1221     GOTO_OPCODE(ip)                     @ jump to next instruction
   1222 #endif
   1223 
   1224 /* ------------------------------ */
   1225     .balign 64
   1226 .L_OP_PACKED_SWITCH: /* 0x2b */
   1227 /* File: armv5te/OP_PACKED_SWITCH.S */
   1228     /*
   1229      * Handle a packed-switch or sparse-switch instruction.  In both cases
   1230      * we decode it and hand it off to a helper function.
   1231      *
   1232      * We don't really expect backward branches in a switch statement, but
   1233      * they're perfectly legal, so we check for them here.
   1234      *
   1235      * for: packed-switch, sparse-switch
   1236      */
   1237     /* op vAA, +BBBB */
   1238     FETCH(r0, 1)                        @ r0<- bbbb (lo)
   1239     FETCH(r1, 2)                        @ r1<- BBBB (hi)
   1240     mov     r3, rINST, lsr #8           @ r3<- AA
   1241     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
   1242     GET_VREG(r1, r3)                    @ r1<- vAA
   1243     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
   1244     bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
   1245     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
   1246     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1247     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
   1248 #if defined(WITH_JIT)
   1249     GET_JIT_PROF_TABLE(r0)
   1250     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1251     cmp     r0,#0
   1252     bne     common_updateProfile
   1253     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1254     GOTO_OPCODE(ip)                     @ jump to next instruction
   1255 #else
   1256     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1257     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1258     GOTO_OPCODE(ip)                     @ jump to next instruction
   1259 #endif
   1260 
   1261 /* ------------------------------ */
   1262     .balign 64
   1263 .L_OP_SPARSE_SWITCH: /* 0x2c */
   1264 /* File: armv5te/OP_SPARSE_SWITCH.S */
   1265 /* File: armv5te/OP_PACKED_SWITCH.S */
   1266     /*
   1267      * Handle a packed-switch or sparse-switch instruction.  In both cases
   1268      * we decode it and hand it off to a helper function.
   1269      *
   1270      * We don't really expect backward branches in a switch statement, but
   1271      * they're perfectly legal, so we check for them here.
   1272      *
   1273      * for: packed-switch, sparse-switch
   1274      */
   1275     /* op vAA, +BBBB */
   1276     FETCH(r0, 1)                        @ r0<- bbbb (lo)
   1277     FETCH(r1, 2)                        @ r1<- BBBB (hi)
   1278     mov     r3, rINST, lsr #8           @ r3<- AA
   1279     orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
   1280     GET_VREG(r1, r3)                    @ r1<- vAA
   1281     add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
   1282     bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
   1283     movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
   1284     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1285     beq     common_backwardBranch       @ (want to use BLE but V is unknown)
   1286 #if defined(WITH_JIT)
   1287     GET_JIT_PROF_TABLE(r0)
   1288     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1289     cmp     r0,#0
   1290     bne     common_updateProfile
   1291     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1292     GOTO_OPCODE(ip)                     @ jump to next instruction
   1293 #else
   1294     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1295     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1296     GOTO_OPCODE(ip)                     @ jump to next instruction
   1297 #endif
   1298 
   1299 
   1300 /* ------------------------------ */
   1301     .balign 64
   1302 .L_OP_CMPL_FLOAT: /* 0x2d */
   1303 /* File: arm-vfp/OP_CMPL_FLOAT.S */
   1304     /*
   1305      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1306      * destination register based on the results of the comparison.
   1307      *
   1308      * int compare(x, y) {
   1309      *     if (x == y) {
   1310      *         return 0;
   1311      *     } else if (x > y) {
   1312      *         return 1;
   1313      *     } else if (x < y) {
   1314      *         return -1;
   1315      *     } else {
   1316      *         return -1;
   1317      *     }
   1318      * }
   1319      */
   1320     /* op vAA, vBB, vCC */
   1321     FETCH(r0, 1)                        @ r0<- CCBB
   1322     mov     r9, rINST, lsr #8           @ r9<- AA
   1323     and     r2, r0, #255                @ r2<- BB
   1324     mov     r3, r0, lsr #8              @ r3<- CC
   1325     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1326     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1327     flds    s0, [r2]                    @ s0<- vBB
   1328     flds    s1, [r3]                    @ s1<- vCC
   1329     fcmpes  s0, s1                      @ compare (vBB, vCC)
   1330     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1331     mvn     r0, #0                      @ r0<- -1 (default)
   1332     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1333     fmstat                              @ export status flags
   1334     movgt   r0, #1                      @ (greater than) r1<- 1
   1335     moveq   r0, #0                      @ (equal) r1<- 0
   1336     b       .LOP_CMPL_FLOAT_finish          @ argh
   1337 
   1338 
   1339 /* ------------------------------ */
   1340     .balign 64
   1341 .L_OP_CMPG_FLOAT: /* 0x2e */
   1342 /* File: arm-vfp/OP_CMPG_FLOAT.S */
   1343     /*
   1344      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1345      * destination register based on the results of the comparison.
   1346      *
   1347      * int compare(x, y) {
   1348      *     if (x == y) {
   1349      *         return 0;
   1350      *     } else if (x < y) {
   1351      *         return -1;
   1352      *     } else if (x > y) {
   1353      *         return 1;
   1354      *     } else {
   1355      *         return 1;
   1356      *     }
   1357      * }
   1358      */
   1359     /* op vAA, vBB, vCC */
   1360     FETCH(r0, 1)                        @ r0<- CCBB
   1361     mov     r9, rINST, lsr #8           @ r9<- AA
   1362     and     r2, r0, #255                @ r2<- BB
   1363     mov     r3, r0, lsr #8              @ r3<- CC
   1364     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1365     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1366     flds    s0, [r2]                    @ s0<- vBB
   1367     flds    s1, [r3]                    @ s1<- vCC
   1368     fcmpes  s0, s1                      @ compare (vBB, vCC)
   1369     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1370     mov     r0, #1                      @ r0<- 1 (default)
   1371     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1372     fmstat                              @ export status flags
   1373     mvnmi   r0, #0                      @ (less than) r1<- -1
   1374     moveq   r0, #0                      @ (equal) r1<- 0
   1375     b       .LOP_CMPG_FLOAT_finish          @ argh
   1376 
   1377 
   1378 /* ------------------------------ */
   1379     .balign 64
   1380 .L_OP_CMPL_DOUBLE: /* 0x2f */
   1381 /* File: arm-vfp/OP_CMPL_DOUBLE.S */
   1382     /*
   1383      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1384      * destination register based on the results of the comparison.
   1385      *
   1386      * int compare(x, y) {
   1387      *     if (x == y) {
   1388      *         return 0;
   1389      *     } else if (x > y) {
   1390      *         return 1;
   1391      *     } else if (x < y) {
   1392      *         return -1;
   1393      *     } else {
   1394      *         return -1;
   1395      *     }
   1396      * }
   1397      */
   1398     /* op vAA, vBB, vCC */
   1399     FETCH(r0, 1)                        @ r0<- CCBB
   1400     mov     r9, rINST, lsr #8           @ r9<- AA
   1401     and     r2, r0, #255                @ r2<- BB
   1402     mov     r3, r0, lsr #8              @ r3<- CC
   1403     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1404     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1405     fldd    d0, [r2]                    @ d0<- vBB
   1406     fldd    d1, [r3]                    @ d1<- vCC
   1407     fcmped  d0, d1                      @ compare (vBB, vCC)
   1408     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1409     mvn     r0, #0                      @ r0<- -1 (default)
   1410     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1411     fmstat                              @ export status flags
   1412     movgt   r0, #1                      @ (greater than) r1<- 1
   1413     moveq   r0, #0                      @ (equal) r1<- 0
   1414     b       .LOP_CMPL_DOUBLE_finish          @ argh
   1415 
   1416 
   1417 /* ------------------------------ */
   1418     .balign 64
   1419 .L_OP_CMPG_DOUBLE: /* 0x30 */
   1420 /* File: arm-vfp/OP_CMPG_DOUBLE.S */
   1421     /*
   1422      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1423      * destination register based on the results of the comparison.
   1424      *
   1425      * int compare(x, y) {
   1426      *     if (x == y) {
   1427      *         return 0;
   1428      *     } else if (x < y) {
   1429      *         return -1;
   1430      *     } else if (x > y) {
   1431      *         return 1;
   1432      *     } else {
   1433      *         return 1;
   1434      *     }
   1435      * }
   1436      */
   1437     /* op vAA, vBB, vCC */
   1438     FETCH(r0, 1)                        @ r0<- CCBB
   1439     mov     r9, rINST, lsr #8           @ r9<- AA
   1440     and     r2, r0, #255                @ r2<- BB
   1441     mov     r3, r0, lsr #8              @ r3<- CC
   1442     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   1443     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   1444     fldd    d0, [r2]                    @ d0<- vBB
   1445     fldd    d1, [r3]                    @ d1<- vCC
   1446     fcmped  d0, d1                      @ compare (vBB, vCC)
   1447     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1448     mov     r0, #1                      @ r0<- 1 (default)
   1449     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1450     fmstat                              @ export status flags
   1451     mvnmi   r0, #0                      @ (less than) r1<- -1
   1452     moveq   r0, #0                      @ (equal) r1<- 0
   1453     b       .LOP_CMPG_DOUBLE_finish          @ argh
   1454 
   1455 
   1456 /* ------------------------------ */
   1457     .balign 64
   1458 .L_OP_CMP_LONG: /* 0x31 */
   1459 /* File: armv5te/OP_CMP_LONG.S */
   1460     /*
   1461      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
   1462      * register based on the results of the comparison.
   1463      *
   1464      * We load the full values with LDM, but in practice many values could
   1465      * be resolved by only looking at the high word.  This could be made
   1466      * faster or slower by splitting the LDM into a pair of LDRs.
   1467      *
   1468      * If we just wanted to set condition flags, we could do this:
   1469      *  subs    ip, r0, r2
   1470      *  sbcs    ip, r1, r3
   1471      *  subeqs  ip, r0, r2
   1472      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
   1473      * integer value, which we can do with 2 conditional mov/mvn instructions
   1474      * (set 1, set -1; if they're equal we already have 0 in ip), giving
   1475      * us a constant 5-cycle path plus a branch at the end to the
   1476      * instruction epilogue code.  The multi-compare approach below needs
   1477      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
   1478      * in the worst case (the 64-bit values are equal).
   1479      */
   1480     /* cmp-long vAA, vBB, vCC */
   1481     FETCH(r0, 1)                        @ r0<- CCBB
   1482     mov     r9, rINST, lsr #8           @ r9<- AA
   1483     and     r2, r0, #255                @ r2<- BB
   1484     mov     r3, r0, lsr #8              @ r3<- CC
   1485     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   1486     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   1487     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   1488     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   1489     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
   1490     blt     .LOP_CMP_LONG_less            @ signed compare on high part
   1491     bgt     .LOP_CMP_LONG_greater
   1492     subs    r1, r0, r2                  @ r1<- r0 - r2
   1493     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
   1494     bne     .LOP_CMP_LONG_less
   1495     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
   1496 
   1497 /* ------------------------------ */
   1498     .balign 64
   1499 .L_OP_IF_EQ: /* 0x32 */
   1500 /* File: armv5te/OP_IF_EQ.S */
   1501 /* File: armv5te/bincmp.S */
   1502     /*
   1503      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1504      * fragment that specifies the *reverse* comparison to perform, e.g.
   1505      * for "if-le" you would use "gt".
   1506      *
   1507      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1508      */
   1509     /* if-cmp vA, vB, +CCCC */
   1510     mov     r0, rINST, lsr #8           @ r0<- A+
   1511     mov     r1, rINST, lsr #12          @ r1<- B
   1512     and     r0, r0, #15
   1513     GET_VREG(r3, r1)                    @ r3<- vB
   1514     GET_VREG(r2, r0)                    @ r2<- vA
   1515     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1516     cmp     r2, r3                      @ compare (vA, vB)
   1517     bne  1f                      @ branch to 1 if comparison failed
   1518     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1519     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1520     bmi     common_backwardBranch       @ yes, do periodic checks
   1521 1:
   1522 #if defined(WITH_JIT)
   1523     GET_JIT_PROF_TABLE(r0)
   1524     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1525     b        common_testUpdateProfile
   1526 #else
   1527     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1528     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1529     GOTO_OPCODE(ip)                     @ jump to next instruction
   1530 #endif
   1531 
   1532 
   1533 /* ------------------------------ */
   1534     .balign 64
   1535 .L_OP_IF_NE: /* 0x33 */
   1536 /* File: armv5te/OP_IF_NE.S */
   1537 /* File: armv5te/bincmp.S */
   1538     /*
   1539      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1540      * fragment that specifies the *reverse* comparison to perform, e.g.
   1541      * for "if-le" you would use "gt".
   1542      *
   1543      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1544      */
   1545     /* if-cmp vA, vB, +CCCC */
   1546     mov     r0, rINST, lsr #8           @ r0<- A+
   1547     mov     r1, rINST, lsr #12          @ r1<- B
   1548     and     r0, r0, #15
   1549     GET_VREG(r3, r1)                    @ r3<- vB
   1550     GET_VREG(r2, r0)                    @ r2<- vA
   1551     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1552     cmp     r2, r3                      @ compare (vA, vB)
   1553     beq  1f                      @ branch to 1 if comparison failed
   1554     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1555     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1556     bmi     common_backwardBranch       @ yes, do periodic checks
   1557 1:
   1558 #if defined(WITH_JIT)
   1559     GET_JIT_PROF_TABLE(r0)
   1560     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1561     b        common_testUpdateProfile
   1562 #else
   1563     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1564     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1565     GOTO_OPCODE(ip)                     @ jump to next instruction
   1566 #endif
   1567 
   1568 
   1569 /* ------------------------------ */
   1570     .balign 64
   1571 .L_OP_IF_LT: /* 0x34 */
   1572 /* File: armv5te/OP_IF_LT.S */
   1573 /* File: armv5te/bincmp.S */
   1574     /*
   1575      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1576      * fragment that specifies the *reverse* comparison to perform, e.g.
   1577      * for "if-le" you would use "gt".
   1578      *
   1579      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1580      */
   1581     /* if-cmp vA, vB, +CCCC */
   1582     mov     r0, rINST, lsr #8           @ r0<- A+
   1583     mov     r1, rINST, lsr #12          @ r1<- B
   1584     and     r0, r0, #15
   1585     GET_VREG(r3, r1)                    @ r3<- vB
   1586     GET_VREG(r2, r0)                    @ r2<- vA
   1587     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1588     cmp     r2, r3                      @ compare (vA, vB)
   1589     bge  1f                      @ branch to 1 if comparison failed
   1590     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1591     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1592     bmi     common_backwardBranch       @ yes, do periodic checks
   1593 1:
   1594 #if defined(WITH_JIT)
   1595     GET_JIT_PROF_TABLE(r0)
   1596     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1597     b        common_testUpdateProfile
   1598 #else
   1599     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1600     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1601     GOTO_OPCODE(ip)                     @ jump to next instruction
   1602 #endif
   1603 
   1604 
   1605 /* ------------------------------ */
   1606     .balign 64
   1607 .L_OP_IF_GE: /* 0x35 */
   1608 /* File: armv5te/OP_IF_GE.S */
   1609 /* File: armv5te/bincmp.S */
   1610     /*
   1611      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1612      * fragment that specifies the *reverse* comparison to perform, e.g.
   1613      * for "if-le" you would use "gt".
   1614      *
   1615      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1616      */
   1617     /* if-cmp vA, vB, +CCCC */
   1618     mov     r0, rINST, lsr #8           @ r0<- A+
   1619     mov     r1, rINST, lsr #12          @ r1<- B
   1620     and     r0, r0, #15
   1621     GET_VREG(r3, r1)                    @ r3<- vB
   1622     GET_VREG(r2, r0)                    @ r2<- vA
   1623     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1624     cmp     r2, r3                      @ compare (vA, vB)
   1625     blt  1f                      @ branch to 1 if comparison failed
   1626     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1627     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1628     bmi     common_backwardBranch       @ yes, do periodic checks
   1629 1:
   1630 #if defined(WITH_JIT)
   1631     GET_JIT_PROF_TABLE(r0)
   1632     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1633     b        common_testUpdateProfile
   1634 #else
   1635     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1636     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1637     GOTO_OPCODE(ip)                     @ jump to next instruction
   1638 #endif
   1639 
   1640 
   1641 /* ------------------------------ */
   1642     .balign 64
   1643 .L_OP_IF_GT: /* 0x36 */
   1644 /* File: armv5te/OP_IF_GT.S */
   1645 /* File: armv5te/bincmp.S */
   1646     /*
   1647      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1648      * fragment that specifies the *reverse* comparison to perform, e.g.
   1649      * for "if-le" you would use "gt".
   1650      *
   1651      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1652      */
   1653     /* if-cmp vA, vB, +CCCC */
   1654     mov     r0, rINST, lsr #8           @ r0<- A+
   1655     mov     r1, rINST, lsr #12          @ r1<- B
   1656     and     r0, r0, #15
   1657     GET_VREG(r3, r1)                    @ r3<- vB
   1658     GET_VREG(r2, r0)                    @ r2<- vA
   1659     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1660     cmp     r2, r3                      @ compare (vA, vB)
   1661     ble  1f                      @ branch to 1 if comparison failed
   1662     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1663     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1664     bmi     common_backwardBranch       @ yes, do periodic checks
   1665 1:
   1666 #if defined(WITH_JIT)
   1667     GET_JIT_PROF_TABLE(r0)
   1668     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1669     b        common_testUpdateProfile
   1670 #else
   1671     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1672     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1673     GOTO_OPCODE(ip)                     @ jump to next instruction
   1674 #endif
   1675 
   1676 
   1677 /* ------------------------------ */
   1678     .balign 64
   1679 .L_OP_IF_LE: /* 0x37 */
   1680 /* File: armv5te/OP_IF_LE.S */
   1681 /* File: armv5te/bincmp.S */
   1682     /*
   1683      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1684      * fragment that specifies the *reverse* comparison to perform, e.g.
   1685      * for "if-le" you would use "gt".
   1686      *
   1687      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1688      */
   1689     /* if-cmp vA, vB, +CCCC */
   1690     mov     r0, rINST, lsr #8           @ r0<- A+
   1691     mov     r1, rINST, lsr #12          @ r1<- B
   1692     and     r0, r0, #15
   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: armv5te/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: armv5te/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: armv5te/OP_IPUT.S */
   2605     /*
   2606      * General 32-bit instance field put.
   2607      *
   2608      * for: iput, 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: armv5te/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: armv5te/OP_NEG_INT.S */
   3494 /* File: armv5te/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     mov     r9, rINST, lsr #8           @ r9<- A+
   3506     GET_VREG(r0, r3)                    @ r0<- vB
   3507     and     r9, r9, #15
   3508                                @ optional op; may set condition codes
   3509     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3510     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
   3511     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3512     SET_VREG(r0, r9)                    @ vAA<- r0
   3513     GOTO_OPCODE(ip)                     @ jump to next instruction
   3514     /* 9-10 instructions */
   3515 
   3516 
   3517 /* ------------------------------ */
   3518     .balign 64
   3519 .L_OP_NOT_INT: /* 0x7c */
   3520 /* File: armv5te/OP_NOT_INT.S */
   3521 /* File: armv5te/unop.S */
   3522     /*
   3523      * Generic 32-bit unary operation.  Provide an "instr" line that
   3524      * specifies an instruction that performs "result = op r0".
   3525      * This could be an ARM instruction or a function call.
   3526      *
   3527      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3528      *      int-to-byte, int-to-char, int-to-short
   3529      */
   3530     /* unop vA, vB */
   3531     mov     r3, rINST, lsr #12          @ r3<- B
   3532     mov     r9, rINST, lsr #8           @ r9<- A+
   3533     GET_VREG(r0, r3)                    @ r0<- vB
   3534     and     r9, r9, #15
   3535                                @ optional op; may set condition codes
   3536     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3537     mvn     r0, r0                              @ r0<- op, r0-r3 changed
   3538     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3539     SET_VREG(r0, r9)                    @ vAA<- r0
   3540     GOTO_OPCODE(ip)                     @ jump to next instruction
   3541     /* 9-10 instructions */
   3542 
   3543 
   3544 /* ------------------------------ */
   3545     .balign 64
   3546 .L_OP_NEG_LONG: /* 0x7d */
   3547 /* File: armv5te/OP_NEG_LONG.S */
   3548 /* File: armv5te/unopWide.S */
   3549     /*
   3550      * Generic 64-bit unary operation.  Provide an "instr" line that
   3551      * specifies an instruction that performs "result = op r0/r1".
   3552      * This could be an ARM instruction or a function call.
   3553      *
   3554      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3555      */
   3556     /* unop vA, vB */
   3557     mov     r9, rINST, lsr #8           @ r9<- A+
   3558     mov     r3, rINST, lsr #12          @ r3<- B
   3559     and     r9, r9, #15
   3560     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3561     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3562     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3563     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3564     rsbs    r0, r0, #0                           @ optional op; may set condition codes
   3565     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
   3566     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3567     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3568     GOTO_OPCODE(ip)                     @ jump to next instruction
   3569     /* 12-13 instructions */
   3570 
   3571 
   3572 /* ------------------------------ */
   3573     .balign 64
   3574 .L_OP_NOT_LONG: /* 0x7e */
   3575 /* File: armv5te/OP_NOT_LONG.S */
   3576 /* File: armv5te/unopWide.S */
   3577     /*
   3578      * Generic 64-bit unary operation.  Provide an "instr" line that
   3579      * specifies an instruction that performs "result = op r0/r1".
   3580      * This could be an ARM instruction or a function call.
   3581      *
   3582      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3583      */
   3584     /* unop vA, vB */
   3585     mov     r9, rINST, lsr #8           @ r9<- A+
   3586     mov     r3, rINST, lsr #12          @ r3<- B
   3587     and     r9, r9, #15
   3588     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3589     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3590     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3591     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3592     mvn     r0, r0                           @ optional op; may set condition codes
   3593     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
   3594     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3595     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3596     GOTO_OPCODE(ip)                     @ jump to next instruction
   3597     /* 12-13 instructions */
   3598 
   3599 
   3600 /* ------------------------------ */
   3601     .balign 64
   3602 .L_OP_NEG_FLOAT: /* 0x7f */
   3603 /* File: armv5te/OP_NEG_FLOAT.S */
   3604 /* File: armv5te/unop.S */
   3605     /*
   3606      * Generic 32-bit unary operation.  Provide an "instr" line that
   3607      * specifies an instruction that performs "result = op r0".
   3608      * This could be an ARM instruction or a function call.
   3609      *
   3610      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3611      *      int-to-byte, int-to-char, int-to-short
   3612      */
   3613     /* unop vA, vB */
   3614     mov     r3, rINST, lsr #12          @ r3<- B
   3615     mov     r9, rINST, lsr #8           @ r9<- A+
   3616     GET_VREG(r0, r3)                    @ r0<- vB
   3617     and     r9, r9, #15
   3618                                @ optional op; may set condition codes
   3619     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3620     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
   3621     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3622     SET_VREG(r0, r9)                    @ vAA<- r0
   3623     GOTO_OPCODE(ip)                     @ jump to next instruction
   3624     /* 9-10 instructions */
   3625 
   3626 
   3627 /* ------------------------------ */
   3628     .balign 64
   3629 .L_OP_NEG_DOUBLE: /* 0x80 */
   3630 /* File: armv5te/OP_NEG_DOUBLE.S */
   3631 /* File: armv5te/unopWide.S */
   3632     /*
   3633      * Generic 64-bit unary operation.  Provide an "instr" line that
   3634      * specifies an instruction that performs "result = op r0/r1".
   3635      * This could be an ARM instruction or a function call.
   3636      *
   3637      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3638      */
   3639     /* unop vA, vB */
   3640     mov     r9, rINST, lsr #8           @ r9<- A+
   3641     mov     r3, rINST, lsr #12          @ r3<- B
   3642     and     r9, r9, #15
   3643     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3644     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3645     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3646     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3647                                @ optional op; may set condition codes
   3648     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
   3649     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3650     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3651     GOTO_OPCODE(ip)                     @ jump to next instruction
   3652     /* 12-13 instructions */
   3653 
   3654 
   3655 /* ------------------------------ */
   3656     .balign 64
   3657 .L_OP_INT_TO_LONG: /* 0x81 */
   3658 /* File: armv5te/OP_INT_TO_LONG.S */
   3659 /* File: armv5te/unopWider.S */
   3660     /*
   3661      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3662      * that specifies an instruction that performs "result = op r0", where
   3663      * "result" is a 64-bit quantity in r0/r1.
   3664      *
   3665      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3666      */
   3667     /* unop vA, vB */
   3668     mov     r9, rINST, lsr #8           @ r9<- A+
   3669     mov     r3, rINST, lsr #12          @ r3<- B
   3670     and     r9, r9, #15
   3671     GET_VREG(r0, r3)                    @ r0<- vB
   3672     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3673                                @ optional op; may set condition codes
   3674     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3675     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
   3676     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3677     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3678     GOTO_OPCODE(ip)                     @ jump to next instruction
   3679     /* 10-11 instructions */
   3680 
   3681 
   3682 /* ------------------------------ */
   3683     .balign 64
   3684 .L_OP_INT_TO_FLOAT: /* 0x82 */
   3685 /* File: arm-vfp/OP_INT_TO_FLOAT.S */
   3686 /* File: arm-vfp/funop.S */
   3687     /*
   3688      * Generic 32-bit unary floating-point operation.  Provide an "instr"
   3689      * line that specifies an instruction that performs "s1 = op s0".
   3690      *
   3691      * for: int-to-float, float-to-int
   3692      */
   3693     /* unop vA, vB */
   3694     mov     r3, rINST, lsr #12          @ r3<- B
   3695     mov     r9, rINST, lsr #8           @ r9<- A+
   3696     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3697     flds    s0, [r3]                    @ s0<- vB
   3698     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3699     and     r9, r9, #15                 @ r9<- A
   3700     fsitos  s1, s0                              @ s1<- op
   3701     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3702     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3703     fsts    s1, [r9]                    @ vA<- s1
   3704     GOTO_OPCODE(ip)                     @ jump to next instruction
   3705 
   3706 
   3707 /* ------------------------------ */
   3708     .balign 64
   3709 .L_OP_INT_TO_DOUBLE: /* 0x83 */
   3710 /* File: arm-vfp/OP_INT_TO_DOUBLE.S */
   3711 /* File: arm-vfp/funopWider.S */
   3712     /*
   3713      * Generic 32bit-to-64bit floating point unary operation.  Provide an
   3714      * "instr" line that specifies an instruction that performs "d0 = op s0".
   3715      *
   3716      * For: int-to-double, float-to-double
   3717      */
   3718     /* unop vA, vB */
   3719     mov     r3, rINST, lsr #12          @ r3<- B
   3720     mov     r9, rINST, lsr #8           @ r9<- A+
   3721     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3722     flds    s0, [r3]                    @ s0<- vB
   3723     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3724     and     r9, r9, #15                 @ r9<- A
   3725     fsitod  d0, s0                              @ d0<- op
   3726     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3727     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3728     fstd    d0, [r9]                    @ vA<- d0
   3729     GOTO_OPCODE(ip)                     @ jump to next instruction
   3730 
   3731 
   3732 /* ------------------------------ */
   3733     .balign 64
   3734 .L_OP_LONG_TO_INT: /* 0x84 */
   3735 /* File: armv5te/OP_LONG_TO_INT.S */
   3736 /* we ignore the high word, making this equivalent to a 32-bit reg move */
   3737 /* File: armv5te/OP_MOVE.S */
   3738     /* for move, move-object, long-to-int */
   3739     /* op vA, vB */
   3740     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
   3741     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
   3742     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3743     GET_VREG(r2, r1)                    @ r2<- fp[B]
   3744     and     r0, r0, #15
   3745     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
   3746     SET_VREG(r2, r0)                    @ fp[A]<- r2
   3747     GOTO_OPCODE(ip)                     @ execute next instruction
   3748 
   3749 
   3750 /* ------------------------------ */
   3751     .balign 64
   3752 .L_OP_LONG_TO_FLOAT: /* 0x85 */
   3753 /* File: armv5te/OP_LONG_TO_FLOAT.S */
   3754 /* File: armv5te/unopNarrower.S */
   3755     /*
   3756      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
   3757      * that specifies an instruction that performs "result = op r0/r1", where
   3758      * "result" is a 32-bit quantity in r0.
   3759      *
   3760      * For: long-to-float, double-to-int, double-to-float
   3761      *
   3762      * (This would work for long-to-int, but that instruction is actually
   3763      * an exact match for OP_MOVE.)
   3764      */
   3765     /* unop vA, vB */
   3766     mov     r3, rINST, lsr #12          @ r3<- B
   3767     mov     r9, rINST, lsr #8           @ r9<- A+
   3768     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3769     and     r9, r9, #15
   3770     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
   3771     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3772                                @ optional op; may set condition codes
   3773     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
   3774     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3775     SET_VREG(r0, r9)                    @ vA<- r0
   3776     GOTO_OPCODE(ip)                     @ jump to next instruction
   3777     /* 10-11 instructions */
   3778 
   3779 
   3780 /* ------------------------------ */
   3781     .balign 64
   3782 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
   3783 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
   3784 /* File: armv5te/unopWide.S */
   3785     /*
   3786      * Generic 64-bit unary operation.  Provide an "instr" line that
   3787      * specifies an instruction that performs "result = op r0/r1".
   3788      * This could be an ARM instruction or a function call.
   3789      *
   3790      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3791      */
   3792     /* unop vA, vB */
   3793     mov     r9, rINST, lsr #8           @ r9<- A+
   3794     mov     r3, rINST, lsr #12          @ r3<- B
   3795     and     r9, r9, #15
   3796     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3797     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3798     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3799     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3800                                @ optional op; may set condition codes
   3801     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
   3802     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3803     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3804     GOTO_OPCODE(ip)                     @ jump to next instruction
   3805     /* 12-13 instructions */
   3806 
   3807 
   3808 /* ------------------------------ */
   3809     .balign 64
   3810 .L_OP_FLOAT_TO_INT: /* 0x87 */
   3811 /* File: arm-vfp/OP_FLOAT_TO_INT.S */
   3812 /* File: arm-vfp/funop.S */
   3813     /*
   3814      * Generic 32-bit unary floating-point operation.  Provide an "instr"
   3815      * line that specifies an instruction that performs "s1 = op s0".
   3816      *
   3817      * for: int-to-float, float-to-int
   3818      */
   3819     /* unop vA, vB */
   3820     mov     r3, rINST, lsr #12          @ r3<- B
   3821     mov     r9, rINST, lsr #8           @ r9<- A+
   3822     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3823     flds    s0, [r3]                    @ s0<- vB
   3824     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3825     and     r9, r9, #15                 @ r9<- A
   3826     ftosizs s1, s0                              @ s1<- op
   3827     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3828     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3829     fsts    s1, [r9]                    @ vA<- s1
   3830     GOTO_OPCODE(ip)                     @ jump to next instruction
   3831 
   3832 
   3833 /* ------------------------------ */
   3834     .balign 64
   3835 .L_OP_FLOAT_TO_LONG: /* 0x88 */
   3836 /* File: armv5te/OP_FLOAT_TO_LONG.S */
   3837 @include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
   3838 /* File: armv5te/unopWider.S */
   3839     /*
   3840      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3841      * that specifies an instruction that performs "result = op r0", where
   3842      * "result" is a 64-bit quantity in r0/r1.
   3843      *
   3844      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3845      */
   3846     /* unop vA, vB */
   3847     mov     r9, rINST, lsr #8           @ r9<- A+
   3848     mov     r3, rINST, lsr #12          @ r3<- B
   3849     and     r9, r9, #15
   3850     GET_VREG(r0, r3)                    @ r0<- vB
   3851     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3852                                @ optional op; may set condition codes
   3853     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3854     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
   3855     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3856     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3857     GOTO_OPCODE(ip)                     @ jump to next instruction
   3858     /* 10-11 instructions */
   3859 
   3860 
   3861 
   3862 /* ------------------------------ */
   3863     .balign 64
   3864 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
   3865 /* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
   3866 /* File: arm-vfp/funopWider.S */
   3867     /*
   3868      * Generic 32bit-to-64bit floating point unary operation.  Provide an
   3869      * "instr" line that specifies an instruction that performs "d0 = op s0".
   3870      *
   3871      * For: int-to-double, float-to-double
   3872      */
   3873     /* unop vA, vB */
   3874     mov     r3, rINST, lsr #12          @ r3<- B
   3875     mov     r9, rINST, lsr #8           @ r9<- A+
   3876     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3877     flds    s0, [r3]                    @ s0<- vB
   3878     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3879     and     r9, r9, #15                 @ r9<- A
   3880     fcvtds  d0, s0                              @ d0<- op
   3881     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3882     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3883     fstd    d0, [r9]                    @ vA<- d0
   3884     GOTO_OPCODE(ip)                     @ jump to next instruction
   3885 
   3886 
   3887 /* ------------------------------ */
   3888     .balign 64
   3889 .L_OP_DOUBLE_TO_INT: /* 0x8a */
   3890 /* File: arm-vfp/OP_DOUBLE_TO_INT.S */
   3891 /* File: arm-vfp/funopNarrower.S */
   3892     /*
   3893      * Generic 64bit-to-32bit unary floating point operation.  Provide an
   3894      * "instr" line that specifies an instruction that performs "s0 = op d0".
   3895      *
   3896      * For: double-to-int, double-to-float
   3897      */
   3898     /* unop vA, vB */
   3899     mov     r3, rINST, lsr #12          @ r3<- B
   3900     mov     r9, rINST, lsr #8           @ r9<- A+
   3901     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3902     fldd    d0, [r3]                    @ d0<- vB
   3903     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3904     and     r9, r9, #15                 @ r9<- A
   3905     ftosizd  s0, d0                              @ s0<- op
   3906     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3907     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3908     fsts    s0, [r9]                    @ vA<- s0
   3909     GOTO_OPCODE(ip)                     @ jump to next instruction
   3910 
   3911 
   3912 /* ------------------------------ */
   3913     .balign 64
   3914 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
   3915 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
   3916 @include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
   3917 /* File: armv5te/unopWide.S */
   3918     /*
   3919      * Generic 64-bit unary operation.  Provide an "instr" line that
   3920      * specifies an instruction that performs "result = op r0/r1".
   3921      * This could be an ARM instruction or a function call.
   3922      *
   3923      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3924      */
   3925     /* unop vA, vB */
   3926     mov     r9, rINST, lsr #8           @ r9<- A+
   3927     mov     r3, rINST, lsr #12          @ r3<- B
   3928     and     r9, r9, #15
   3929     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3930     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3931     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3932     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3933                                @ optional op; may set condition codes
   3934     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
   3935     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3936     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3937     GOTO_OPCODE(ip)                     @ jump to next instruction
   3938     /* 12-13 instructions */
   3939 
   3940 
   3941 
   3942 /* ------------------------------ */
   3943     .balign 64
   3944 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
   3945 /* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
   3946 /* File: arm-vfp/funopNarrower.S */
   3947     /*
   3948      * Generic 64bit-to-32bit unary floating point operation.  Provide an
   3949      * "instr" line that specifies an instruction that performs "s0 = op d0".
   3950      *
   3951      * For: double-to-int, double-to-float
   3952      */
   3953     /* unop vA, vB */
   3954     mov     r3, rINST, lsr #12          @ r3<- B
   3955     mov     r9, rINST, lsr #8           @ r9<- A+
   3956     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   3957     fldd    d0, [r3]                    @ d0<- vB
   3958     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3959     and     r9, r9, #15                 @ r9<- A
   3960     fcvtsd  s0, d0                              @ s0<- op
   3961     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3962     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   3963     fsts    s0, [r9]                    @ vA<- s0
   3964     GOTO_OPCODE(ip)                     @ jump to next instruction
   3965 
   3966 
   3967 /* ------------------------------ */
   3968     .balign 64
   3969 .L_OP_INT_TO_BYTE: /* 0x8d */
   3970 /* File: armv5te/OP_INT_TO_BYTE.S */
   3971 /* File: armv5te/unop.S */
   3972     /*
   3973      * Generic 32-bit unary operation.  Provide an "instr" line that
   3974      * specifies an instruction that performs "result = op r0".
   3975      * This could be an ARM instruction or a function call.
   3976      *
   3977      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3978      *      int-to-byte, int-to-char, int-to-short
   3979      */
   3980     /* unop vA, vB */
   3981     mov     r3, rINST, lsr #12          @ r3<- B
   3982     mov     r9, rINST, lsr #8           @ r9<- A+
   3983     GET_VREG(r0, r3)                    @ r0<- vB
   3984     and     r9, r9, #15
   3985     mov     r0, r0, asl #24                           @ optional op; may set condition codes
   3986     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3987     mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
   3988     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3989     SET_VREG(r0, r9)                    @ vAA<- r0
   3990     GOTO_OPCODE(ip)                     @ jump to next instruction
   3991     /* 9-10 instructions */
   3992 
   3993 
   3994 /* ------------------------------ */
   3995     .balign 64
   3996 .L_OP_INT_TO_CHAR: /* 0x8e */
   3997 /* File: armv5te/OP_INT_TO_CHAR.S */
   3998 /* File: armv5te/unop.S */
   3999     /*
   4000      * Generic 32-bit unary operation.  Provide an "instr" line that
   4001      * specifies an instruction that performs "result = op r0".
   4002      * This could be an ARM instruction or a function call.
   4003      *
   4004      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   4005      *      int-to-byte, int-to-char, int-to-short
   4006      */
   4007     /* unop vA, vB */
   4008     mov     r3, rINST, lsr #12          @ r3<- B
   4009     mov     r9, rINST, lsr #8           @ r9<- A+
   4010     GET_VREG(r0, r3)                    @ r0<- vB
   4011     and     r9, r9, #15
   4012     mov     r0, r0, asl #16                           @ optional op; may set condition codes
   4013     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4014     mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
   4015     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4016     SET_VREG(r0, r9)                    @ vAA<- r0
   4017     GOTO_OPCODE(ip)                     @ jump to next instruction
   4018     /* 9-10 instructions */
   4019 
   4020 
   4021 /* ------------------------------ */
   4022     .balign 64
   4023 .L_OP_INT_TO_SHORT: /* 0x8f */
   4024 /* File: armv5te/OP_INT_TO_SHORT.S */
   4025 /* File: armv5te/unop.S */
   4026     /*
   4027      * Generic 32-bit unary operation.  Provide an "instr" line that
   4028      * specifies an instruction that performs "result = op r0".
   4029      * This could be an ARM instruction or a function call.
   4030      *
   4031      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   4032      *      int-to-byte, int-to-char, int-to-short
   4033      */
   4034     /* unop vA, vB */
   4035     mov     r3, rINST, lsr #12          @ r3<- B
   4036     mov     r9, rINST, lsr #8           @ r9<- A+
   4037     GET_VREG(r0, r3)                    @ r0<- vB
   4038     and     r9, r9, #15
   4039     mov     r0, r0, asl #16                           @ optional op; may set condition codes
   4040     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4041     mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
   4042     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4043     SET_VREG(r0, r9)                    @ vAA<- r0
   4044     GOTO_OPCODE(ip)                     @ jump to next instruction
   4045     /* 9-10 instructions */
   4046 
   4047 
   4048 /* ------------------------------ */
   4049     .balign 64
   4050 .L_OP_ADD_INT: /* 0x90 */
   4051 /* File: armv5te/OP_ADD_INT.S */
   4052 /* File: armv5te/binop.S */
   4053     /*
   4054      * Generic 32-bit binary operation.  Provide an "instr" line that
   4055      * specifies an instruction that performs "result = r0 op r1".
   4056      * This could be an ARM instruction or a function call.  (If the result
   4057      * comes back in a register other than r0, you can override "result".)
   4058      *
   4059      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4060      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4061      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4062      * handles it correctly.
   4063      *
   4064      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4065      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4066      *      mul-float, div-float, rem-float
   4067      */
   4068     /* binop vAA, vBB, vCC */
   4069     FETCH(r0, 1)                        @ r0<- CCBB
   4070     mov     r9, rINST, lsr #8           @ r9<- AA
   4071     mov     r3, r0, lsr #8              @ r3<- CC
   4072     and     r2, r0, #255                @ r2<- BB
   4073     GET_VREG(r1, r3)                    @ r1<- vCC
   4074     GET_VREG(r0, r2)                    @ r0<- vBB
   4075     .if 0
   4076     cmp     r1, #0                      @ is second operand zero?
   4077     beq     common_errDivideByZero
   4078     .endif
   4079 
   4080     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4081                                @ optional op; may set condition codes
   4082     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4083     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4084     SET_VREG(r0, r9)               @ vAA<- r0
   4085     GOTO_OPCODE(ip)                     @ jump to next instruction
   4086     /* 11-14 instructions */
   4087 
   4088 
   4089 /* ------------------------------ */
   4090     .balign 64
   4091 .L_OP_SUB_INT: /* 0x91 */
   4092 /* File: armv5te/OP_SUB_INT.S */
   4093 /* File: armv5te/binop.S */
   4094     /*
   4095      * Generic 32-bit binary operation.  Provide an "instr" line that
   4096      * specifies an instruction that performs "result = r0 op r1".
   4097      * This could be an ARM instruction or a function call.  (If the result
   4098      * comes back in a register other than r0, you can override "result".)
   4099      *
   4100      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4101      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4102      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4103      * handles it correctly.
   4104      *
   4105      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4106      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4107      *      mul-float, div-float, rem-float
   4108      */
   4109     /* binop vAA, vBB, vCC */
   4110     FETCH(r0, 1)                        @ r0<- CCBB
   4111     mov     r9, rINST, lsr #8           @ r9<- AA
   4112     mov     r3, r0, lsr #8              @ r3<- CC
   4113     and     r2, r0, #255                @ r2<- BB
   4114     GET_VREG(r1, r3)                    @ r1<- vCC
   4115     GET_VREG(r0, r2)                    @ r0<- vBB
   4116     .if 0
   4117     cmp     r1, #0                      @ is second operand zero?
   4118     beq     common_errDivideByZero
   4119     .endif
   4120 
   4121     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4122                                @ optional op; may set condition codes
   4123     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4124     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4125     SET_VREG(r0, r9)               @ vAA<- r0
   4126     GOTO_OPCODE(ip)                     @ jump to next instruction
   4127     /* 11-14 instructions */
   4128 
   4129 
   4130 /* ------------------------------ */
   4131     .balign 64
   4132 .L_OP_MUL_INT: /* 0x92 */
   4133 /* File: armv5te/OP_MUL_INT.S */
   4134 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   4135 /* File: armv5te/binop.S */
   4136     /*
   4137      * Generic 32-bit binary operation.  Provide an "instr" line that
   4138      * specifies an instruction that performs "result = r0 op r1".
   4139      * This could be an ARM instruction or a function call.  (If the result
   4140      * comes back in a register other than r0, you can override "result".)
   4141      *
   4142      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4143      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4144      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4145      * handles it correctly.
   4146      *
   4147      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4148      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4149      *      mul-float, div-float, rem-float
   4150      */
   4151     /* binop vAA, vBB, vCC */
   4152     FETCH(r0, 1)                        @ r0<- CCBB
   4153     mov     r9, rINST, lsr #8           @ r9<- AA
   4154     mov     r3, r0, lsr #8              @ r3<- CC
   4155     and     r2, r0, #255                @ r2<- BB
   4156     GET_VREG(r1, r3)                    @ r1<- vCC
   4157     GET_VREG(r0, r2)                    @ r0<- vBB
   4158     .if 0
   4159     cmp     r1, #0                      @ is second operand zero?
   4160     beq     common_errDivideByZero
   4161     .endif
   4162 
   4163     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4164                                @ optional op; may set condition codes
   4165     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   4166     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4167     SET_VREG(r0, r9)               @ vAA<- r0
   4168     GOTO_OPCODE(ip)                     @ jump to next instruction
   4169     /* 11-14 instructions */
   4170 
   4171 
   4172 /* ------------------------------ */
   4173     .balign 64
   4174 .L_OP_DIV_INT: /* 0x93 */
   4175 /* File: armv5te/OP_DIV_INT.S */
   4176 /* File: armv5te/binop.S */
   4177     /*
   4178      * Generic 32-bit binary operation.  Provide an "instr" line that
   4179      * specifies an instruction that performs "result = r0 op r1".
   4180      * This could be an ARM instruction or a function call.  (If the result
   4181      * comes back in a register other than r0, you can override "result".)
   4182      *
   4183      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4184      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4185      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4186      * handles it correctly.
   4187      *
   4188      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4189      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4190      *      mul-float, div-float, rem-float
   4191      */
   4192     /* binop vAA, vBB, vCC */
   4193     FETCH(r0, 1)                        @ r0<- CCBB
   4194     mov     r9, rINST, lsr #8           @ r9<- AA
   4195     mov     r3, r0, lsr #8              @ r3<- CC
   4196     and     r2, r0, #255                @ r2<- BB
   4197     GET_VREG(r1, r3)                    @ r1<- vCC
   4198     GET_VREG(r0, r2)                    @ r0<- vBB
   4199     .if 1
   4200     cmp     r1, #0                      @ is second operand zero?
   4201     beq     common_errDivideByZero
   4202     .endif
   4203 
   4204     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4205                                @ optional op; may set condition codes
   4206     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   4207     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4208     SET_VREG(r0, r9)               @ vAA<- r0
   4209     GOTO_OPCODE(ip)                     @ jump to next instruction
   4210     /* 11-14 instructions */
   4211 
   4212 
   4213 /* ------------------------------ */
   4214     .balign 64
   4215 .L_OP_REM_INT: /* 0x94 */
   4216 /* File: armv5te/OP_REM_INT.S */
   4217 /* idivmod returns quotient in r0 and remainder in r1 */
   4218 /* File: armv5te/binop.S */
   4219     /*
   4220      * Generic 32-bit binary operation.  Provide an "instr" line that
   4221      * specifies an instruction that performs "result = r0 op r1".
   4222      * This could be an ARM instruction or a function call.  (If the result
   4223      * comes back in a register other than r0, you can override "result".)
   4224      *
   4225      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4226      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4227      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4228      * handles it correctly.
   4229      *
   4230      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4231      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4232      *      mul-float, div-float, rem-float
   4233      */
   4234     /* binop vAA, vBB, vCC */
   4235     FETCH(r0, 1)                        @ r0<- CCBB
   4236     mov     r9, rINST, lsr #8           @ r9<- AA
   4237     mov     r3, r0, lsr #8              @ r3<- CC
   4238     and     r2, r0, #255                @ r2<- BB
   4239     GET_VREG(r1, r3)                    @ r1<- vCC
   4240     GET_VREG(r0, r2)                    @ r0<- vBB
   4241     .if 1
   4242     cmp     r1, #0                      @ is second operand zero?
   4243     beq     common_errDivideByZero
   4244     .endif
   4245 
   4246     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4247                                @ optional op; may set condition codes
   4248     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   4249     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4250     SET_VREG(r1, r9)               @ vAA<- r1
   4251     GOTO_OPCODE(ip)                     @ jump to next instruction
   4252     /* 11-14 instructions */
   4253 
   4254 
   4255 /* ------------------------------ */
   4256     .balign 64
   4257 .L_OP_AND_INT: /* 0x95 */
   4258 /* File: armv5te/OP_AND_INT.S */
   4259 /* File: armv5te/binop.S */
   4260     /*
   4261      * Generic 32-bit binary operation.  Provide an "instr" line that
   4262      * specifies an instruction that performs "result = r0 op r1".
   4263      * This could be an ARM instruction or a function call.  (If the result
   4264      * comes back in a register other than r0, you can override "result".)
   4265      *
   4266      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4267      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4268      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4269      * handles it correctly.
   4270      *
   4271      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4272      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4273      *      mul-float, div-float, rem-float
   4274      */
   4275     /* binop vAA, vBB, vCC */
   4276     FETCH(r0, 1)                        @ r0<- CCBB
   4277     mov     r9, rINST, lsr #8           @ r9<- AA
   4278     mov     r3, r0, lsr #8              @ r3<- CC
   4279     and     r2, r0, #255                @ r2<- BB
   4280     GET_VREG(r1, r3)                    @ r1<- vCC
   4281     GET_VREG(r0, r2)                    @ r0<- vBB
   4282     .if 0
   4283     cmp     r1, #0                      @ is second operand zero?
   4284     beq     common_errDivideByZero
   4285     .endif
   4286 
   4287     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4288                                @ optional op; may set condition codes
   4289     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4290     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4291     SET_VREG(r0, r9)               @ vAA<- r0
   4292     GOTO_OPCODE(ip)                     @ jump to next instruction
   4293     /* 11-14 instructions */
   4294 
   4295 
   4296 /* ------------------------------ */
   4297     .balign 64
   4298 .L_OP_OR_INT: /* 0x96 */
   4299 /* File: armv5te/OP_OR_INT.S */
   4300 /* File: armv5te/binop.S */
   4301     /*
   4302      * Generic 32-bit binary operation.  Provide an "instr" line that
   4303      * specifies an instruction that performs "result = r0 op r1".
   4304      * This could be an ARM instruction or a function call.  (If the result
   4305      * comes back in a register other than r0, you can override "result".)
   4306      *
   4307      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4308      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4309      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4310      * handles it correctly.
   4311      *
   4312      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4313      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4314      *      mul-float, div-float, rem-float
   4315      */
   4316     /* binop vAA, vBB, vCC */
   4317     FETCH(r0, 1)                        @ r0<- CCBB
   4318     mov     r9, rINST, lsr #8           @ r9<- AA
   4319     mov     r3, r0, lsr #8              @ r3<- CC
   4320     and     r2, r0, #255                @ r2<- BB
   4321     GET_VREG(r1, r3)                    @ r1<- vCC
   4322     GET_VREG(r0, r2)                    @ r0<- vBB
   4323     .if 0
   4324     cmp     r1, #0                      @ is second operand zero?
   4325     beq     common_errDivideByZero
   4326     .endif
   4327 
   4328     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4329                                @ optional op; may set condition codes
   4330     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4331     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4332     SET_VREG(r0, r9)               @ vAA<- r0
   4333     GOTO_OPCODE(ip)                     @ jump to next instruction
   4334     /* 11-14 instructions */
   4335 
   4336 
   4337 /* ------------------------------ */
   4338     .balign 64
   4339 .L_OP_XOR_INT: /* 0x97 */
   4340 /* File: armv5te/OP_XOR_INT.S */
   4341 /* File: armv5te/binop.S */
   4342     /*
   4343      * Generic 32-bit binary operation.  Provide an "instr" line that
   4344      * specifies an instruction that performs "result = r0 op r1".
   4345      * This could be an ARM instruction or a function call.  (If the result
   4346      * comes back in a register other than r0, you can override "result".)
   4347      *
   4348      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4349      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4350      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4351      * handles it correctly.
   4352      *
   4353      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4354      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4355      *      mul-float, div-float, rem-float
   4356      */
   4357     /* binop vAA, vBB, vCC */
   4358     FETCH(r0, 1)                        @ r0<- CCBB
   4359     mov     r9, rINST, lsr #8           @ r9<- AA
   4360     mov     r3, r0, lsr #8              @ r3<- CC
   4361     and     r2, r0, #255                @ r2<- BB
   4362     GET_VREG(r1, r3)                    @ r1<- vCC
   4363     GET_VREG(r0, r2)                    @ r0<- vBB
   4364     .if 0
   4365     cmp     r1, #0                      @ is second operand zero?
   4366     beq     common_errDivideByZero
   4367     .endif
   4368 
   4369     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4370                                @ optional op; may set condition codes
   4371     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4372     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4373     SET_VREG(r0, r9)               @ vAA<- r0
   4374     GOTO_OPCODE(ip)                     @ jump to next instruction
   4375     /* 11-14 instructions */
   4376 
   4377 
   4378 /* ------------------------------ */
   4379     .balign 64
   4380 .L_OP_SHL_INT: /* 0x98 */
   4381 /* File: armv5te/OP_SHL_INT.S */
   4382 /* File: armv5te/binop.S */
   4383     /*
   4384      * Generic 32-bit binary operation.  Provide an "instr" line that
   4385      * specifies an instruction that performs "result = r0 op r1".
   4386      * This could be an ARM instruction or a function call.  (If the result
   4387      * comes back in a register other than r0, you can override "result".)
   4388      *
   4389      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4390      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4391      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4392      * handles it correctly.
   4393      *
   4394      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4395      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4396      *      mul-float, div-float, rem-float
   4397      */
   4398     /* binop vAA, vBB, vCC */
   4399     FETCH(r0, 1)                        @ r0<- CCBB
   4400     mov     r9, rINST, lsr #8           @ r9<- AA
   4401     mov     r3, r0, lsr #8              @ r3<- CC
   4402     and     r2, r0, #255                @ r2<- BB
   4403     GET_VREG(r1, r3)                    @ r1<- vCC
   4404     GET_VREG(r0, r2)                    @ r0<- vBB
   4405     .if 0
   4406     cmp     r1, #0                      @ is second operand zero?
   4407     beq     common_errDivideByZero
   4408     .endif
   4409 
   4410     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4411     and     r1, r1, #31                           @ optional op; may set condition codes
   4412     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   4413     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4414     SET_VREG(r0, r9)               @ vAA<- r0
   4415     GOTO_OPCODE(ip)                     @ jump to next instruction
   4416     /* 11-14 instructions */
   4417 
   4418 
   4419 /* ------------------------------ */
   4420     .balign 64
   4421 .L_OP_SHR_INT: /* 0x99 */
   4422 /* File: armv5te/OP_SHR_INT.S */
   4423 /* File: armv5te/binop.S */
   4424     /*
   4425      * Generic 32-bit binary operation.  Provide an "instr" line that
   4426      * specifies an instruction that performs "result = r0 op r1".
   4427      * This could be an ARM instruction or a function call.  (If the result
   4428      * comes back in a register other than r0, you can override "result".)
   4429      *
   4430      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4431      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4432      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4433      * handles it correctly.
   4434      *
   4435      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4436      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4437      *      mul-float, div-float, rem-float
   4438      */
   4439     /* binop vAA, vBB, vCC */
   4440     FETCH(r0, 1)                        @ r0<- CCBB
   4441     mov     r9, rINST, lsr #8           @ r9<- AA
   4442     mov     r3, r0, lsr #8              @ r3<- CC
   4443     and     r2, r0, #255                @ r2<- BB
   4444     GET_VREG(r1, r3)                    @ r1<- vCC
   4445     GET_VREG(r0, r2)                    @ r0<- vBB
   4446     .if 0
   4447     cmp     r1, #0                      @ is second operand zero?
   4448     beq     common_errDivideByZero
   4449     .endif
   4450 
   4451     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4452     and     r1, r1, #31                           @ optional op; may set condition codes
   4453     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   4454     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4455     SET_VREG(r0, r9)               @ vAA<- r0
   4456     GOTO_OPCODE(ip)                     @ jump to next instruction
   4457     /* 11-14 instructions */
   4458 
   4459 
   4460 /* ------------------------------ */
   4461     .balign 64
   4462 .L_OP_USHR_INT: /* 0x9a */
   4463 /* File: armv5te/OP_USHR_INT.S */
   4464 /* File: armv5te/binop.S */
   4465     /*
   4466      * Generic 32-bit binary operation.  Provide an "instr" line that
   4467      * specifies an instruction that performs "result = r0 op r1".
   4468      * This could be an ARM instruction or a function call.  (If the result
   4469      * comes back in a register other than r0, you can override "result".)
   4470      *
   4471      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4472      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4473      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4474      * handles it correctly.
   4475      *
   4476      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4477      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4478      *      mul-float, div-float, rem-float
   4479      */
   4480     /* binop vAA, vBB, vCC */
   4481     FETCH(r0, 1)                        @ r0<- CCBB
   4482     mov     r9, rINST, lsr #8           @ r9<- AA
   4483     mov     r3, r0, lsr #8              @ r3<- CC
   4484     and     r2, r0, #255                @ r2<- BB
   4485     GET_VREG(r1, r3)                    @ r1<- vCC
   4486     GET_VREG(r0, r2)                    @ r0<- vBB
   4487     .if 0
   4488     cmp     r1, #0                      @ is second operand zero?
   4489     beq     common_errDivideByZero
   4490     .endif
   4491 
   4492     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4493     and     r1, r1, #31                           @ optional op; may set condition codes
   4494     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   4495     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4496     SET_VREG(r0, r9)               @ vAA<- r0
   4497     GOTO_OPCODE(ip)                     @ jump to next instruction
   4498     /* 11-14 instructions */
   4499 
   4500 
   4501 /* ------------------------------ */
   4502     .balign 64
   4503 .L_OP_ADD_LONG: /* 0x9b */
   4504 /* File: armv5te/OP_ADD_LONG.S */
   4505 /* File: armv5te/binopWide.S */
   4506     /*
   4507      * Generic 64-bit binary operation.  Provide an "instr" line that
   4508      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4509      * This could be an ARM instruction or a function call.  (If the result
   4510      * comes back in a register other than r0, you can override "result".)
   4511      *
   4512      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4513      * vCC (r1).  Useful for integer division and modulus.
   4514      *
   4515      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4516      *      xor-long, add-double, sub-double, mul-double, div-double,
   4517      *      rem-double
   4518      *
   4519      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4520      */
   4521     /* binop vAA, vBB, vCC */
   4522     FETCH(r0, 1)                        @ r0<- CCBB
   4523     mov     r9, rINST, lsr #8           @ r9<- AA
   4524     and     r2, r0, #255                @ r2<- BB
   4525     mov     r3, r0, lsr #8              @ r3<- CC
   4526     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4527     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4528     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4529     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4530     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4531     .if 0
   4532     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4533     beq     common_errDivideByZero
   4534     .endif
   4535     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4536 
   4537     adds    r0, r0, r2                           @ optional op; may set condition codes
   4538     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
   4539     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4540     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4541     GOTO_OPCODE(ip)                     @ jump to next instruction
   4542     /* 14-17 instructions */
   4543 
   4544 
   4545 /* ------------------------------ */
   4546     .balign 64
   4547 .L_OP_SUB_LONG: /* 0x9c */
   4548 /* File: armv5te/OP_SUB_LONG.S */
   4549 /* File: armv5te/binopWide.S */
   4550     /*
   4551      * Generic 64-bit binary operation.  Provide an "instr" line that
   4552      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4553      * This could be an ARM instruction or a function call.  (If the result
   4554      * comes back in a register other than r0, you can override "result".)
   4555      *
   4556      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4557      * vCC (r1).  Useful for integer division and modulus.
   4558      *
   4559      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4560      *      xor-long, add-double, sub-double, mul-double, div-double,
   4561      *      rem-double
   4562      *
   4563      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4564      */
   4565     /* binop vAA, vBB, vCC */
   4566     FETCH(r0, 1)                        @ r0<- CCBB
   4567     mov     r9, rINST, lsr #8           @ r9<- AA
   4568     and     r2, r0, #255                @ r2<- BB
   4569     mov     r3, r0, lsr #8              @ r3<- CC
   4570     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4571     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4572     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4573     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4574     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4575     .if 0
   4576     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4577     beq     common_errDivideByZero
   4578     .endif
   4579     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4580 
   4581     subs    r0, r0, r2                           @ optional op; may set condition codes
   4582     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
   4583     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4584     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4585     GOTO_OPCODE(ip)                     @ jump to next instruction
   4586     /* 14-17 instructions */
   4587 
   4588 
   4589 /* ------------------------------ */
   4590     .balign 64
   4591 .L_OP_MUL_LONG: /* 0x9d */
   4592 /* File: armv5te/OP_MUL_LONG.S */
   4593     /*
   4594      * Signed 64-bit integer multiply.
   4595      *
   4596      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
   4597      *        WX
   4598      *      x YZ
   4599      *  --------
   4600      *     ZW ZX
   4601      *  YW YX
   4602      *
   4603      * The low word of the result holds ZX, the high word holds
   4604      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
   4605      * it doesn't fit in the low 64 bits.
   4606      *
   4607      * Unlike most ARM math operations, multiply instructions have
   4608      * restrictions on using the same register more than once (Rd and Rm
   4609      * cannot be the same).
   4610      */
   4611     /* mul-long vAA, vBB, vCC */
   4612     FETCH(r0, 1)                        @ r0<- CCBB
   4613     and     r2, r0, #255                @ r2<- BB
   4614     mov     r3, r0, lsr #8              @ r3<- CC
   4615     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4616     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4617     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4618     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4619     mul     ip, r2, r1                  @  ip<- ZxW
   4620     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
   4621     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
   4622     mov     r0, rINST, lsr #8           @ r0<- AA
   4623     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
   4624     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
   4625     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4626     b       .LOP_MUL_LONG_finish
   4627 
   4628 /* ------------------------------ */
   4629     .balign 64
   4630 .L_OP_DIV_LONG: /* 0x9e */
   4631 /* File: armv5te/OP_DIV_LONG.S */
   4632 /* File: armv5te/binopWide.S */
   4633     /*
   4634      * Generic 64-bit binary operation.  Provide an "instr" line that
   4635      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4636      * This could be an ARM instruction or a function call.  (If the result
   4637      * comes back in a register other than r0, you can override "result".)
   4638      *
   4639      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4640      * vCC (r1).  Useful for integer division and modulus.
   4641      *
   4642      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4643      *      xor-long, add-double, sub-double, mul-double, div-double,
   4644      *      rem-double
   4645      *
   4646      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4647      */
   4648     /* binop vAA, vBB, vCC */
   4649     FETCH(r0, 1)                        @ r0<- CCBB
   4650     mov     r9, rINST, lsr #8           @ r9<- AA
   4651     and     r2, r0, #255                @ r2<- BB
   4652     mov     r3, r0, lsr #8              @ r3<- CC
   4653     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4654     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4655     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4656     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4657     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4658     .if 1
   4659     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4660     beq     common_errDivideByZero
   4661     .endif
   4662     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4663 
   4664                                @ optional op; may set condition codes
   4665     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   4666     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4667     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4668     GOTO_OPCODE(ip)                     @ jump to next instruction
   4669     /* 14-17 instructions */
   4670 
   4671 
   4672 /* ------------------------------ */
   4673     .balign 64
   4674 .L_OP_REM_LONG: /* 0x9f */
   4675 /* File: armv5te/OP_REM_LONG.S */
   4676 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
   4677 /* File: armv5te/binopWide.S */
   4678     /*
   4679      * Generic 64-bit binary operation.  Provide an "instr" line that
   4680      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4681      * This could be an ARM instruction or a function call.  (If the result
   4682      * comes back in a register other than r0, you can override "result".)
   4683      *
   4684      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4685      * vCC (r1).  Useful for integer division and modulus.
   4686      *
   4687      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4688      *      xor-long, add-double, sub-double, mul-double, div-double,
   4689      *      rem-double
   4690      *
   4691      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4692      */
   4693     /* binop vAA, vBB, vCC */
   4694     FETCH(r0, 1)                        @ r0<- CCBB
   4695     mov     r9, rINST, lsr #8           @ r9<- AA
   4696     and     r2, r0, #255                @ r2<- BB
   4697     mov     r3, r0, lsr #8              @ r3<- CC
   4698     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4699     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4700     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4701     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4702     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4703     .if 1
   4704     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4705     beq     common_errDivideByZero
   4706     .endif
   4707     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4708 
   4709                                @ optional op; may set condition codes
   4710     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   4711     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4712     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
   4713     GOTO_OPCODE(ip)                     @ jump to next instruction
   4714     /* 14-17 instructions */
   4715 
   4716 
   4717 /* ------------------------------ */
   4718     .balign 64
   4719 .L_OP_AND_LONG: /* 0xa0 */
   4720 /* File: armv5te/OP_AND_LONG.S */
   4721 /* File: armv5te/binopWide.S */
   4722     /*
   4723      * Generic 64-bit binary operation.  Provide an "instr" line that
   4724      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4725      * This could be an ARM instruction or a function call.  (If the result
   4726      * comes back in a register other than r0, you can override "result".)
   4727      *
   4728      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4729      * vCC (r1).  Useful for integer division and modulus.
   4730      *
   4731      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4732      *      xor-long, add-double, sub-double, mul-double, div-double,
   4733      *      rem-double
   4734      *
   4735      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4736      */
   4737     /* binop vAA, vBB, vCC */
   4738     FETCH(r0, 1)                        @ r0<- CCBB
   4739     mov     r9, rINST, lsr #8           @ r9<- AA
   4740     and     r2, r0, #255                @ r2<- BB
   4741     mov     r3, r0, lsr #8              @ r3<- CC
   4742     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4743     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4744     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4745     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4746     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4747     .if 0
   4748     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4749     beq     common_errDivideByZero
   4750     .endif
   4751     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4752 
   4753     and     r0, r0, r2                           @ optional op; may set condition codes
   4754     and     r1, r1, r3                              @ result<- op, r0-r3 changed
   4755     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4756     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4757     GOTO_OPCODE(ip)                     @ jump to next instruction
   4758     /* 14-17 instructions */
   4759 
   4760 
   4761 /* ------------------------------ */
   4762     .balign 64
   4763 .L_OP_OR_LONG: /* 0xa1 */
   4764 /* File: armv5te/OP_OR_LONG.S */
   4765 /* File: armv5te/binopWide.S */
   4766     /*
   4767      * Generic 64-bit binary operation.  Provide an "instr" line that
   4768      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4769      * This could be an ARM instruction or a function call.  (If the result
   4770      * comes back in a register other than r0, you can override "result".)
   4771      *
   4772      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4773      * vCC (r1).  Useful for integer division and modulus.
   4774      *
   4775      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4776      *      xor-long, add-double, sub-double, mul-double, div-double,
   4777      *      rem-double
   4778      *
   4779      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4780      */
   4781     /* binop vAA, vBB, vCC */
   4782     FETCH(r0, 1)                        @ r0<- CCBB
   4783     mov     r9, rINST, lsr #8           @ r9<- AA
   4784     and     r2, r0, #255                @ r2<- BB
   4785     mov     r3, r0, lsr #8              @ r3<- CC
   4786     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4787     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4788     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4789     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4790     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4791     .if 0
   4792     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4793     beq     common_errDivideByZero
   4794     .endif
   4795     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4796 
   4797     orr     r0, r0, r2                           @ optional op; may set condition codes
   4798     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
   4799     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4800     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4801     GOTO_OPCODE(ip)                     @ jump to next instruction
   4802     /* 14-17 instructions */
   4803 
   4804 
   4805 /* ------------------------------ */
   4806     .balign 64
   4807 .L_OP_XOR_LONG: /* 0xa2 */
   4808 /* File: armv5te/OP_XOR_LONG.S */
   4809 /* File: armv5te/binopWide.S */
   4810     /*
   4811      * Generic 64-bit binary operation.  Provide an "instr" line that
   4812      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4813      * This could be an ARM instruction or a function call.  (If the result
   4814      * comes back in a register other than r0, you can override "result".)
   4815      *
   4816      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4817      * vCC (r1).  Useful for integer division and modulus.
   4818      *
   4819      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4820      *      xor-long, add-double, sub-double, mul-double, div-double,
   4821      *      rem-double
   4822      *
   4823      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4824      */
   4825     /* binop vAA, vBB, vCC */
   4826     FETCH(r0, 1)                        @ r0<- CCBB
   4827     mov     r9, rINST, lsr #8           @ r9<- AA
   4828     and     r2, r0, #255                @ r2<- BB
   4829     mov     r3, r0, lsr #8              @ r3<- CC
   4830     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4831     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4832     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4833     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4834     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4835     .if 0
   4836     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4837     beq     common_errDivideByZero
   4838     .endif
   4839     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4840 
   4841     eor     r0, r0, r2                           @ optional op; may set condition codes
   4842     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
   4843     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4844     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4845     GOTO_OPCODE(ip)                     @ jump to next instruction
   4846     /* 14-17 instructions */
   4847 
   4848 
   4849 /* ------------------------------ */
   4850     .balign 64
   4851 .L_OP_SHL_LONG: /* 0xa3 */
   4852 /* File: armv5te/OP_SHL_LONG.S */
   4853     /*
   4854      * Long integer shift.  This is different from the generic 32/64-bit
   4855      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4856      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4857      * 6 bits of the shift distance.
   4858      */
   4859     /* shl-long vAA, vBB, vCC */
   4860     FETCH(r0, 1)                        @ r0<- CCBB
   4861     mov     r9, rINST, lsr #8           @ r9<- AA
   4862     and     r3, r0, #255                @ r3<- BB
   4863     mov     r0, r0, lsr #8              @ r0<- CC
   4864     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4865     GET_VREG(r2, r0)                    @ r2<- vCC
   4866     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4867     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   4868     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4869 
   4870     mov     r1, r1, asl r2              @  r1<- r1 << r2
   4871     rsb     r3, r2, #32                 @  r3<- 32 - r2
   4872     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
   4873     subs    ip, r2, #32                 @  ip<- r2 - 32
   4874     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
   4875     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4876     b       .LOP_SHL_LONG_finish
   4877 
   4878 /* ------------------------------ */
   4879     .balign 64
   4880 .L_OP_SHR_LONG: /* 0xa4 */
   4881 /* File: armv5te/OP_SHR_LONG.S */
   4882     /*
   4883      * Long integer shift.  This is different from the generic 32/64-bit
   4884      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4885      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4886      * 6 bits of the shift distance.
   4887      */
   4888     /* shr-long vAA, vBB, vCC */
   4889     FETCH(r0, 1)                        @ r0<- CCBB
   4890     mov     r9, rINST, lsr #8           @ r9<- AA
   4891     and     r3, r0, #255                @ r3<- BB
   4892     mov     r0, r0, lsr #8              @ r0<- CC
   4893     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4894     GET_VREG(r2, r0)                    @ r2<- vCC
   4895     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4896     and     r2, r2, #63                 @ r0<- r0 & 0x3f
   4897     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4898 
   4899     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   4900     rsb     r3, r2, #32                 @  r3<- 32 - r2
   4901     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   4902     subs    ip, r2, #32                 @  ip<- r2 - 32
   4903     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
   4904     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4905     b       .LOP_SHR_LONG_finish
   4906 
   4907 /* ------------------------------ */
   4908     .balign 64
   4909 .L_OP_USHR_LONG: /* 0xa5 */
   4910 /* File: armv5te/OP_USHR_LONG.S */
   4911     /*
   4912      * Long integer shift.  This is different from the generic 32/64-bit
   4913      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4914      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4915      * 6 bits of the shift distance.
   4916      */
   4917     /* ushr-long vAA, vBB, vCC */
   4918     FETCH(r0, 1)                        @ r0<- CCBB
   4919     mov     r9, rINST, lsr #8           @ r9<- AA
   4920     and     r3, r0, #255                @ r3<- BB
   4921     mov     r0, r0, lsr #8              @ r0<- CC
   4922     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4923     GET_VREG(r2, r0)                    @ r2<- vCC
   4924     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4925     and     r2, r2, #63                 @ r0<- r0 & 0x3f
   4926     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4927 
   4928     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   4929     rsb     r3, r2, #32                 @  r3<- 32 - r2
   4930     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   4931     subs    ip, r2, #32                 @  ip<- r2 - 32
   4932     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
   4933     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4934     b       .LOP_USHR_LONG_finish
   4935 
   4936 /* ------------------------------ */
   4937     .balign 64
   4938 .L_OP_ADD_FLOAT: /* 0xa6 */
   4939 /* File: arm-vfp/OP_ADD_FLOAT.S */
   4940 /* File: arm-vfp/fbinop.S */
   4941     /*
   4942      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   4943      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   4944      * use the "softfp" ABI, this must be an instruction, not a function call.
   4945      *
   4946      * For: add-float, sub-float, mul-float, div-float
   4947      */
   4948     /* floatop vAA, vBB, vCC */
   4949     FETCH(r0, 1)                        @ r0<- CCBB
   4950     mov     r9, rINST, lsr #8           @ r9<- AA
   4951     mov     r3, r0, lsr #8              @ r3<- CC
   4952     and     r2, r0, #255                @ r2<- BB
   4953     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   4954     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   4955     flds    s1, [r3]                    @ s1<- vCC
   4956     flds    s0, [r2]                    @ s0<- vBB
   4957 
   4958     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4959     fadds   s2, s0, s1                              @ s2<- op
   4960     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4961     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   4962     fsts    s2, [r9]                    @ vAA<- s2
   4963     GOTO_OPCODE(ip)                     @ jump to next instruction
   4964 
   4965 
   4966 /* ------------------------------ */
   4967     .balign 64
   4968 .L_OP_SUB_FLOAT: /* 0xa7 */
   4969 /* File: arm-vfp/OP_SUB_FLOAT.S */
   4970 /* File: arm-vfp/fbinop.S */
   4971     /*
   4972      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   4973      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   4974      * use the "softfp" ABI, this must be an instruction, not a function call.
   4975      *
   4976      * For: add-float, sub-float, mul-float, div-float
   4977      */
   4978     /* floatop vAA, vBB, vCC */
   4979     FETCH(r0, 1)                        @ r0<- CCBB
   4980     mov     r9, rINST, lsr #8           @ r9<- AA
   4981     mov     r3, r0, lsr #8              @ r3<- CC
   4982     and     r2, r0, #255                @ r2<- BB
   4983     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   4984     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   4985     flds    s1, [r3]                    @ s1<- vCC
   4986     flds    s0, [r2]                    @ s0<- vBB
   4987 
   4988     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4989     fsubs   s2, s0, s1                              @ s2<- op
   4990     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4991     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   4992     fsts    s2, [r9]                    @ vAA<- s2
   4993     GOTO_OPCODE(ip)                     @ jump to next instruction
   4994 
   4995 
   4996 /* ------------------------------ */
   4997     .balign 64
   4998 .L_OP_MUL_FLOAT: /* 0xa8 */
   4999 /* File: arm-vfp/OP_MUL_FLOAT.S */
   5000 /* File: arm-vfp/fbinop.S */
   5001     /*
   5002      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   5003      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   5004      * use the "softfp" ABI, this must be an instruction, not a function call.
   5005      *
   5006      * For: add-float, sub-float, mul-float, div-float
   5007      */
   5008     /* floatop vAA, vBB, vCC */
   5009     FETCH(r0, 1)                        @ r0<- CCBB
   5010     mov     r9, rINST, lsr #8           @ r9<- AA
   5011     mov     r3, r0, lsr #8              @ r3<- CC
   5012     and     r2, r0, #255                @ r2<- BB
   5013     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5014     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5015     flds    s1, [r3]                    @ s1<- vCC
   5016     flds    s0, [r2]                    @ s0<- vBB
   5017 
   5018     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5019     fmuls   s2, s0, s1                              @ s2<- op
   5020     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5021     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5022     fsts    s2, [r9]                    @ vAA<- s2
   5023     GOTO_OPCODE(ip)                     @ jump to next instruction
   5024 
   5025 
   5026 /* ------------------------------ */
   5027     .balign 64
   5028 .L_OP_DIV_FLOAT: /* 0xa9 */
   5029 /* File: arm-vfp/OP_DIV_FLOAT.S */
   5030 /* File: arm-vfp/fbinop.S */
   5031     /*
   5032      * Generic 32-bit floating-point operation.  Provide an "instr" line that
   5033      * specifies an instruction that performs "s2 = s0 op s1".  Because we
   5034      * use the "softfp" ABI, this must be an instruction, not a function call.
   5035      *
   5036      * For: add-float, sub-float, mul-float, div-float
   5037      */
   5038     /* floatop vAA, vBB, vCC */
   5039     FETCH(r0, 1)                        @ r0<- CCBB
   5040     mov     r9, rINST, lsr #8           @ r9<- AA
   5041     mov     r3, r0, lsr #8              @ r3<- CC
   5042     and     r2, r0, #255                @ r2<- BB
   5043     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5044     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5045     flds    s1, [r3]                    @ s1<- vCC
   5046     flds    s0, [r2]                    @ s0<- vBB
   5047 
   5048     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5049     fdivs   s2, s0, s1                              @ s2<- op
   5050     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5051     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5052     fsts    s2, [r9]                    @ vAA<- s2
   5053     GOTO_OPCODE(ip)                     @ jump to next instruction
   5054 
   5055 
   5056 /* ------------------------------ */
   5057     .balign 64
   5058 .L_OP_REM_FLOAT: /* 0xaa */
   5059 /* File: armv5te/OP_REM_FLOAT.S */
   5060 /* EABI doesn't define a float remainder function, but libm does */
   5061 /* File: armv5te/binop.S */
   5062     /*
   5063      * Generic 32-bit binary operation.  Provide an "instr" line that
   5064      * specifies an instruction that performs "result = r0 op r1".
   5065      * This could be an ARM instruction or a function call.  (If the result
   5066      * comes back in a register other than r0, you can override "result".)
   5067      *
   5068      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5069      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5070      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5071      * handles it correctly.
   5072      *
   5073      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5074      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5075      *      mul-float, div-float, rem-float
   5076      */
   5077     /* binop vAA, vBB, vCC */
   5078     FETCH(r0, 1)                        @ r0<- CCBB
   5079     mov     r9, rINST, lsr #8           @ r9<- AA
   5080     mov     r3, r0, lsr #8              @ r3<- CC
   5081     and     r2, r0, #255                @ r2<- BB
   5082     GET_VREG(r1, r3)                    @ r1<- vCC
   5083     GET_VREG(r0, r2)                    @ r0<- vBB
   5084     .if 0
   5085     cmp     r1, #0                      @ is second operand zero?
   5086     beq     common_errDivideByZero
   5087     .endif
   5088 
   5089     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5090                                @ optional op; may set condition codes
   5091     bl      fmodf                              @ r0<- op, r0-r3 changed
   5092     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5093     SET_VREG(r0, r9)               @ vAA<- r0
   5094     GOTO_OPCODE(ip)                     @ jump to next instruction
   5095     /* 11-14 instructions */
   5096 
   5097 
   5098 /* ------------------------------ */
   5099     .balign 64
   5100 .L_OP_ADD_DOUBLE: /* 0xab */
   5101 /* File: arm-vfp/OP_ADD_DOUBLE.S */
   5102 /* File: arm-vfp/fbinopWide.S */
   5103     /*
   5104      * Generic 64-bit double-precision floating point binary operation.
   5105      * Provide an "instr" line that specifies an instruction that performs
   5106      * "d2 = d0 op d1".
   5107      *
   5108      * for: add-double, sub-double, mul-double, div-double
   5109      */
   5110     /* doubleop vAA, vBB, vCC */
   5111     FETCH(r0, 1)                        @ r0<- CCBB
   5112     mov     r9, rINST, lsr #8           @ r9<- AA
   5113     mov     r3, r0, lsr #8              @ r3<- CC
   5114     and     r2, r0, #255                @ r2<- BB
   5115     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5116     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5117     fldd    d1, [r3]                    @ d1<- vCC
   5118     fldd    d0, [r2]                    @ d0<- vBB
   5119 
   5120     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5121     faddd   d2, d0, d1                              @ s2<- op
   5122     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5123     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5124     fstd    d2, [r9]                    @ vAA<- d2
   5125     GOTO_OPCODE(ip)                     @ jump to next instruction
   5126 
   5127 
   5128 /* ------------------------------ */
   5129     .balign 64
   5130 .L_OP_SUB_DOUBLE: /* 0xac */
   5131 /* File: arm-vfp/OP_SUB_DOUBLE.S */
   5132 /* File: arm-vfp/fbinopWide.S */
   5133     /*
   5134      * Generic 64-bit double-precision floating point binary operation.
   5135      * Provide an "instr" line that specifies an instruction that performs
   5136      * "d2 = d0 op d1".
   5137      *
   5138      * for: add-double, sub-double, mul-double, div-double
   5139      */
   5140     /* doubleop vAA, vBB, vCC */
   5141     FETCH(r0, 1)                        @ r0<- CCBB
   5142     mov     r9, rINST, lsr #8           @ r9<- AA
   5143     mov     r3, r0, lsr #8              @ r3<- CC
   5144     and     r2, r0, #255                @ r2<- BB
   5145     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5146     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5147     fldd    d1, [r3]                    @ d1<- vCC
   5148     fldd    d0, [r2]                    @ d0<- vBB
   5149 
   5150     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5151     fsubd   d2, d0, d1                              @ s2<- op
   5152     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5153     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5154     fstd    d2, [r9]                    @ vAA<- d2
   5155     GOTO_OPCODE(ip)                     @ jump to next instruction
   5156 
   5157 
   5158 /* ------------------------------ */
   5159     .balign 64
   5160 .L_OP_MUL_DOUBLE: /* 0xad */
   5161 /* File: arm-vfp/OP_MUL_DOUBLE.S */
   5162 /* File: arm-vfp/fbinopWide.S */
   5163     /*
   5164      * Generic 64-bit double-precision floating point binary operation.
   5165      * Provide an "instr" line that specifies an instruction that performs
   5166      * "d2 = d0 op d1".
   5167      *
   5168      * for: add-double, sub-double, mul-double, div-double
   5169      */
   5170     /* doubleop vAA, vBB, vCC */
   5171     FETCH(r0, 1)                        @ r0<- CCBB
   5172     mov     r9, rINST, lsr #8           @ r9<- AA
   5173     mov     r3, r0, lsr #8              @ r3<- CC
   5174     and     r2, r0, #255                @ r2<- BB
   5175     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5176     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5177     fldd    d1, [r3]                    @ d1<- vCC
   5178     fldd    d0, [r2]                    @ d0<- vBB
   5179 
   5180     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5181     fmuld   d2, d0, d1                              @ s2<- op
   5182     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5183     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5184     fstd    d2, [r9]                    @ vAA<- d2
   5185     GOTO_OPCODE(ip)                     @ jump to next instruction
   5186 
   5187 
   5188 /* ------------------------------ */
   5189     .balign 64
   5190 .L_OP_DIV_DOUBLE: /* 0xae */
   5191 /* File: arm-vfp/OP_DIV_DOUBLE.S */
   5192 /* File: arm-vfp/fbinopWide.S */
   5193     /*
   5194      * Generic 64-bit double-precision floating point binary operation.
   5195      * Provide an "instr" line that specifies an instruction that performs
   5196      * "d2 = d0 op d1".
   5197      *
   5198      * for: add-double, sub-double, mul-double, div-double
   5199      */
   5200     /* doubleop vAA, vBB, vCC */
   5201     FETCH(r0, 1)                        @ r0<- CCBB
   5202     mov     r9, rINST, lsr #8           @ r9<- AA
   5203     mov     r3, r0, lsr #8              @ r3<- CC
   5204     and     r2, r0, #255                @ r2<- BB
   5205     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
   5206     VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
   5207     fldd    d1, [r3]                    @ d1<- vCC
   5208     fldd    d0, [r2]                    @ d0<- vBB
   5209 
   5210     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5211     fdivd   d2, d0, d1                              @ s2<- op
   5212     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5213     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
   5214     fstd    d2, [r9]                    @ vAA<- d2
   5215     GOTO_OPCODE(ip)                     @ jump to next instruction
   5216 
   5217 
   5218 /* ------------------------------ */
   5219     .balign 64
   5220 .L_OP_REM_DOUBLE: /* 0xaf */
   5221 /* File: armv5te/OP_REM_DOUBLE.S */
   5222 /* EABI doesn't define a double remainder function, but libm does */
   5223 /* File: armv5te/binopWide.S */
   5224     /*
   5225      * Generic 64-bit binary operation.  Provide an "instr" line that
   5226      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5227      * This could be an ARM instruction or a function call.  (If the result
   5228      * comes back in a register other than r0, you can override "result".)
   5229      *
   5230      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5231      * vCC (r1).  Useful for integer division and modulus.
   5232      *
   5233      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5234      *      xor-long, add-double, sub-double, mul-double, div-double,
   5235      *      rem-double
   5236      *
   5237      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5238      */
   5239     /* binop vAA, vBB, vCC */
   5240     FETCH(r0, 1)                        @ r0<- CCBB
   5241     mov     r9, rINST, lsr #8           @ r9<- AA
   5242     and     r2, r0, #255                @ r2<- BB
   5243     mov     r3, r0, lsr #8              @ r3<- CC
   5244     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5245     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5246     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5247     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5248     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5249     .if 0
   5250     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5251     beq     common_errDivideByZero
   5252     .endif
   5253     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5254 
   5255                                @ optional op; may set condition codes
   5256     bl      fmod                              @ result<- op, r0-r3 changed
   5257     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5258     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5259     GOTO_OPCODE(ip)                     @ jump to next instruction
   5260     /* 14-17 instructions */
   5261 
   5262 
   5263 /* ------------------------------ */
   5264     .balign 64
   5265 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
   5266 /* File: armv5te/OP_ADD_INT_2ADDR.S */
   5267 /* File: armv5te/binop2addr.S */
   5268     /*
   5269      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5270      * that specifies an instruction that performs "result = r0 op r1".
   5271      * This could be an ARM instruction or a function call.  (If the result
   5272      * comes back in a register other than r0, you can override "result".)
   5273      *
   5274      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5275      * vCC (r1).  Useful for integer division and modulus.
   5276      *
   5277      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5278      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5279      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5280      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5281      */
   5282     /* binop/2addr vA, vB */
   5283     mov     r9, rINST, lsr #8           @ r9<- A+
   5284     mov     r3, rINST, lsr #12          @ r3<- B
   5285     and     r9, r9, #15
   5286     GET_VREG(r1, r3)                    @ r1<- vB
   5287     GET_VREG(r0, r9)                    @ r0<- vA
   5288     .if 0
   5289     cmp     r1, #0                      @ is second operand zero?
   5290     beq     common_errDivideByZero
   5291     .endif
   5292     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5293 
   5294                                @ optional op; may set condition codes
   5295     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5296     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5297     SET_VREG(r0, r9)               @ vAA<- r0
   5298     GOTO_OPCODE(ip)                     @ jump to next instruction
   5299     /* 10-13 instructions */
   5300 
   5301 
   5302 /* ------------------------------ */
   5303     .balign 64
   5304 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
   5305 /* File: armv5te/OP_SUB_INT_2ADDR.S */
   5306 /* File: armv5te/binop2addr.S */
   5307     /*
   5308      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5309      * that specifies an instruction that performs "result = r0 op r1".
   5310      * This could be an ARM instruction or a function call.  (If the result
   5311      * comes back in a register other than r0, you can override "result".)
   5312      *
   5313      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5314      * vCC (r1).  Useful for integer division and modulus.
   5315      *
   5316      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5317      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5318      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5319      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5320      */
   5321     /* binop/2addr vA, vB */
   5322     mov     r9, rINST, lsr #8           @ r9<- A+
   5323     mov     r3, rINST, lsr #12          @ r3<- B
   5324     and     r9, r9, #15
   5325     GET_VREG(r1, r3)                    @ r1<- vB
   5326     GET_VREG(r0, r9)                    @ r0<- vA
   5327     .if 0
   5328     cmp     r1, #0                      @ is second operand zero?
   5329     beq     common_errDivideByZero
   5330     .endif
   5331     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5332 
   5333                                @ optional op; may set condition codes
   5334     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5335     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5336     SET_VREG(r0, r9)               @ vAA<- r0
   5337     GOTO_OPCODE(ip)                     @ jump to next instruction
   5338     /* 10-13 instructions */
   5339 
   5340 
   5341 /* ------------------------------ */
   5342     .balign 64
   5343 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
   5344 /* File: armv5te/OP_MUL_INT_2ADDR.S */
   5345 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   5346 /* File: armv5te/binop2addr.S */
   5347     /*
   5348      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5349      * that specifies an instruction that performs "result = r0 op r1".
   5350      * This could be an ARM instruction or a function call.  (If the result
   5351      * comes back in a register other than r0, you can override "result".)
   5352      *
   5353      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5354      * vCC (r1).  Useful for integer division and modulus.
   5355      *
   5356      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5357      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5358      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5359      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5360      */
   5361     /* binop/2addr vA, vB */
   5362     mov     r9, rINST, lsr #8           @ r9<- A+
   5363     mov     r3, rINST, lsr #12          @ r3<- B
   5364     and     r9, r9, #15
   5365     GET_VREG(r1, r3)                    @ r1<- vB
   5366     GET_VREG(r0, r9)                    @ r0<- vA
   5367     .if 0
   5368     cmp     r1, #0                      @ is second operand zero?
   5369     beq     common_errDivideByZero
   5370     .endif
   5371     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5372 
   5373                                @ optional op; may set condition codes
   5374     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   5375     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5376     SET_VREG(r0, r9)               @ vAA<- r0
   5377     GOTO_OPCODE(ip)                     @ jump to next instruction
   5378     /* 10-13 instructions */
   5379 
   5380 
   5381 /* ------------------------------ */
   5382     .balign 64
   5383 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
   5384 /* File: armv5te/OP_DIV_INT_2ADDR.S */
   5385 /* File: armv5te/binop2addr.S */
   5386     /*
   5387      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5388      * that specifies an instruction that performs "result = r0 op r1".
   5389      * This could be an ARM instruction or a function call.  (If the result
   5390      * comes back in a register other than r0, you can override "result".)
   5391      *
   5392      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5393      * vCC (r1).  Useful for integer division and modulus.
   5394      *
   5395      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5396      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5397      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5398      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5399      */
   5400     /* binop/2addr vA, vB */
   5401     mov     r9, rINST, lsr #8           @ r9<- A+
   5402     mov     r3, rINST, lsr #12          @ r3<- B
   5403     and     r9, r9, #15
   5404     GET_VREG(r1, r3)                    @ r1<- vB
   5405     GET_VREG(r0, r9)                    @ r0<- vA
   5406     .if 1
   5407     cmp     r1, #0                      @ is second operand zero?
   5408     beq     common_errDivideByZero
   5409     .endif
   5410     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5411 
   5412                                @ optional op; may set condition codes
   5413     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   5414     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5415     SET_VREG(r0, r9)               @ vAA<- r0
   5416     GOTO_OPCODE(ip)                     @ jump to next instruction
   5417     /* 10-13 instructions */
   5418 
   5419 
   5420 /* ------------------------------ */
   5421     .balign 64
   5422 .L_OP_REM_INT_2ADDR: /* 0xb4 */
   5423 /* File: armv5te/OP_REM_INT_2ADDR.S */
   5424 /* idivmod returns quotient in r0 and remainder in r1 */
   5425 /* File: armv5te/binop2addr.S */
   5426     /*
   5427      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5428      * that specifies an instruction that performs "result = r0 op r1".
   5429      * This could be an ARM instruction or a function call.  (If the result
   5430      * comes back in a register other than r0, you can override "result".)
   5431      *
   5432      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5433      * vCC (r1).  Useful for integer division and modulus.
   5434      *
   5435      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5436      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5437      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5438      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5439      */
   5440     /* binop/2addr vA, vB */
   5441     mov     r9, rINST, lsr #8           @ r9<- A+
   5442     mov     r3, rINST, lsr #12          @ r3<- B
   5443     and     r9, r9, #15
   5444     GET_VREG(r1, r3)                    @ r1<- vB
   5445     GET_VREG(r0, r9)                    @ r0<- vA
   5446     .if 1
   5447     cmp     r1, #0                      @ is second operand zero?
   5448     beq     common_errDivideByZero
   5449     .endif
   5450     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5451 
   5452                                @ optional op; may set condition codes
   5453     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   5454     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5455     SET_VREG(r1, r9)               @ vAA<- r1
   5456     GOTO_OPCODE(ip)                     @ jump to next instruction
   5457     /* 10-13 instructions */
   5458 
   5459 
   5460 /* ------------------------------ */
   5461     .balign 64
   5462 .L_OP_AND_INT_2ADDR: /* 0xb5 */
   5463 /* File: armv5te/OP_AND_INT_2ADDR.S */
   5464 /* File: armv5te/binop2addr.S */
   5465     /*
   5466      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5467      * that specifies an instruction that performs "result = r0 op r1".
   5468      * This could be an ARM instruction or a function call.  (If the result
   5469      * comes back in a register other than r0, you can override "result".)
   5470      *
   5471      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5472      * vCC (r1).  Useful for integer division and modulus.
   5473      *
   5474      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5475      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5476      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5477      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5478      */
   5479     /* binop/2addr vA, vB */
   5480     mov     r9, rINST, lsr #8           @ r9<- A+
   5481     mov     r3, rINST, lsr #12          @ r3<- B
   5482     and     r9, r9, #15
   5483     GET_VREG(r1, r3)                    @ r1<- vB
   5484     GET_VREG(r0, r9)                    @ r0<- vA
   5485     .if 0
   5486     cmp     r1, #0                      @ is second operand zero?
   5487     beq     common_errDivideByZero
   5488     .endif
   5489     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5490 
   5491                                @ optional op; may set condition codes
   5492     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5493     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5494     SET_VREG(r0, r9)               @ vAA<- r0
   5495     GOTO_OPCODE(ip)                     @ jump to next instruction
   5496     /* 10-13 instructions */
   5497 
   5498 
   5499 /* ------------------------------ */
   5500     .balign 64
   5501 .L_OP_OR_INT_2ADDR: /* 0xb6 */
   5502 /* File: armv5te/OP_OR_INT_2ADDR.S */
   5503 /* File: armv5te/binop2addr.S */
   5504     /*
   5505      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5506      * that specifies an instruction that performs "result = r0 op r1".
   5507      * This could be an ARM instruction or a function call.  (If the result
   5508      * comes back in a register other than r0, you can override "result".)
   5509      *
   5510      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5511      * vCC (r1).  Useful for integer division and modulus.
   5512      *
   5513      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5514      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5515      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5516      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5517      */
   5518     /* binop/2addr vA, vB */
   5519     mov     r9, rINST, lsr #8           @ r9<- A+
   5520     mov     r3, rINST, lsr #12          @ r3<- B
   5521     and     r9, r9, #15
   5522     GET_VREG(r1, r3)                    @ r1<- vB
   5523     GET_VREG(r0, r9)                    @ r0<- vA
   5524     .if 0
   5525     cmp     r1, #0                      @ is second operand zero?
   5526     beq     common_errDivideByZero
   5527     .endif
   5528     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5529 
   5530                                @ optional op; may set condition codes
   5531     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5532     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5533     SET_VREG(r0, r9)               @ vAA<- r0
   5534     GOTO_OPCODE(ip)                     @ jump to next instruction
   5535     /* 10-13 instructions */
   5536 
   5537 
   5538 /* ------------------------------ */
   5539     .balign 64
   5540 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
   5541 /* File: armv5te/OP_XOR_INT_2ADDR.S */
   5542 /* File: armv5te/binop2addr.S */
   5543     /*
   5544      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5545      * that specifies an instruction that performs "result = r0 op r1".
   5546      * This could be an ARM instruction or a function call.  (If the result
   5547      * comes back in a register other than r0, you can override "result".)
   5548      *
   5549      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5550      * vCC (r1).  Useful for integer division and modulus.
   5551      *
   5552      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5553      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5554      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5555      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5556      */
   5557     /* binop/2addr vA, vB */
   5558     mov     r9, rINST, lsr #8           @ r9<- A+
   5559     mov     r3, rINST, lsr #12          @ r3<- B
   5560     and     r9, r9, #15
   5561     GET_VREG(r1, r3)                    @ r1<- vB
   5562     GET_VREG(r0, r9)                    @ r0<- vA
   5563     .if 0
   5564     cmp     r1, #0                      @ is second operand zero?
   5565     beq     common_errDivideByZero
   5566     .endif
   5567     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5568 
   5569                                @ optional op; may set condition codes
   5570     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5571     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5572     SET_VREG(r0, r9)               @ vAA<- r0
   5573     GOTO_OPCODE(ip)                     @ jump to next instruction
   5574     /* 10-13 instructions */
   5575 
   5576 
   5577 /* ------------------------------ */
   5578     .balign 64
   5579 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
   5580 /* File: armv5te/OP_SHL_INT_2ADDR.S */
   5581 /* File: armv5te/binop2addr.S */
   5582     /*
   5583      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5584      * that specifies an instruction that performs "result = r0 op r1".
   5585      * This could be an ARM instruction or a function call.  (If the result
   5586      * comes back in a register other than r0, you can override "result".)
   5587      *
   5588      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5589      * vCC (r1).  Useful for integer division and modulus.
   5590      *
   5591      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5592      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5593      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5594      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5595      */
   5596     /* binop/2addr vA, vB */
   5597     mov     r9, rINST, lsr #8           @ r9<- A+
   5598     mov     r3, rINST, lsr #12          @ r3<- B
   5599     and     r9, r9, #15
   5600     GET_VREG(r1, r3)                    @ r1<- vB
   5601     GET_VREG(r0, r9)                    @ r0<- vA
   5602     .if 0
   5603     cmp     r1, #0                      @ is second operand zero?
   5604     beq     common_errDivideByZero
   5605     .endif
   5606     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5607 
   5608     and     r1, r1, #31                           @ optional op; may set condition codes
   5609     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   5610     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5611     SET_VREG(r0, r9)               @ vAA<- r0
   5612     GOTO_OPCODE(ip)                     @ jump to next instruction
   5613     /* 10-13 instructions */
   5614 
   5615 
   5616 /* ------------------------------ */
   5617     .balign 64
   5618 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
   5619 /* File: armv5te/OP_SHR_INT_2ADDR.S */
   5620 /* File: armv5te/binop2addr.S */
   5621     /*
   5622      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5623      * that specifies an instruction that performs "result = r0 op r1".
   5624      * This could be an ARM instruction or a function call.  (If the result
   5625      * comes back in a register other than r0, you can override "result".)
   5626      *
   5627      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5628      * vCC (r1).  Useful for integer division and modulus.
   5629      *
   5630      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5631      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5632      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5633      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5634      */
   5635     /* binop/2addr vA, vB */
   5636     mov     r9, rINST, lsr #8           @ r9<- A+
   5637     mov     r3, rINST, lsr #12          @ r3<- B
   5638     and     r9, r9, #15
   5639     GET_VREG(r1, r3)                    @ r1<- vB
   5640     GET_VREG(r0, r9)                    @ r0<- vA
   5641     .if 0
   5642     cmp     r1, #0                      @ is second operand zero?
   5643     beq     common_errDivideByZero
   5644     .endif
   5645     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5646 
   5647     and     r1, r1, #31                           @ optional op; may set condition codes
   5648     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   5649     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5650     SET_VREG(r0, r9)               @ vAA<- r0
   5651     GOTO_OPCODE(ip)                     @ jump to next instruction
   5652     /* 10-13 instructions */
   5653 
   5654 
   5655 /* ------------------------------ */
   5656     .balign 64
   5657 .L_OP_USHR_INT_2ADDR: /* 0xba */
   5658 /* File: armv5te/OP_USHR_INT_2ADDR.S */
   5659 /* File: armv5te/binop2addr.S */
   5660     /*
   5661      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5662      * that specifies an instruction that performs "result = r0 op r1".
   5663      * This could be an ARM instruction or a function call.  (If the result
   5664      * comes back in a register other than r0, you can override "result".)
   5665      *
   5666      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5667      * vCC (r1).  Useful for integer division and modulus.
   5668      *
   5669      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5670      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5671      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5672      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5673      */
   5674     /* binop/2addr vA, vB */
   5675     mov     r9, rINST, lsr #8           @ r9<- A+
   5676     mov     r3, rINST, lsr #12          @ r3<- B
   5677     and     r9, r9, #15
   5678     GET_VREG(r1, r3)                    @ r1<- vB
   5679     GET_VREG(r0, r9)                    @ r0<- vA
   5680     .if 0
   5681     cmp     r1, #0                      @ is second operand zero?
   5682     beq     common_errDivideByZero
   5683     .endif
   5684     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5685 
   5686     and     r1, r1, #31                           @ optional op; may set condition codes
   5687     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   5688     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5689     SET_VREG(r0, r9)               @ vAA<- r0
   5690     GOTO_OPCODE(ip)                     @ jump to next instruction
   5691     /* 10-13 instructions */
   5692 
   5693 
   5694 /* ------------------------------ */
   5695     .balign 64
   5696 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
   5697 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
   5698 /* File: armv5te/binopWide2addr.S */
   5699     /*
   5700      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5701      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5702      * This could be an ARM instruction or a function call.  (If the result
   5703      * comes back in a register other than r0, you can override "result".)
   5704      *
   5705      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5706      * vCC (r1).  Useful for integer division and modulus.
   5707      *
   5708      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5709      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5710      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5711      *      rem-double/2addr
   5712      */
   5713     /* binop/2addr vA, vB */
   5714     mov     r9, rINST, lsr #8           @ r9<- A+
   5715     mov     r1, rINST, lsr #12          @ r1<- B
   5716     and     r9, r9, #15
   5717     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5718     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5719     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5720     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5721     .if 0
   5722     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5723     beq     common_errDivideByZero
   5724     .endif
   5725     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5726 
   5727     adds    r0, r0, r2                           @ optional op; may set condition codes
   5728     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
   5729     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5730     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5731     GOTO_OPCODE(ip)                     @ jump to next instruction
   5732     /* 12-15 instructions */
   5733 
   5734 
   5735 /* ------------------------------ */
   5736     .balign 64
   5737 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
   5738 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
   5739 /* File: armv5te/binopWide2addr.S */
   5740     /*
   5741      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5742      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5743      * This could be an ARM instruction or a function call.  (If the result
   5744      * comes back in a register other than r0, you can override "result".)
   5745      *
   5746      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5747      * vCC (r1).  Useful for integer division and modulus.
   5748      *
   5749      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5750      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5751      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5752      *      rem-double/2addr
   5753      */
   5754     /* binop/2addr vA, vB */
   5755     mov     r9, rINST, lsr #8           @ r9<- A+
   5756     mov     r1, rINST, lsr #12          @ r1<- B
   5757     and     r9, r9, #15
   5758     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5759     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5760     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5761     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5762     .if 0
   5763     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5764     beq     common_errDivideByZero
   5765     .endif
   5766     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5767 
   5768     subs    r0, r0, r2                           @ optional op; may set condition codes
   5769     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
   5770     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5771     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5772     GOTO_OPCODE(ip)                     @ jump to next instruction
   5773     /* 12-15 instructions */
   5774 
   5775 
   5776 /* ------------------------------ */
   5777     .balign 64
   5778 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
   5779 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
   5780     /*
   5781      * Signed 64-bit integer multiply, "/2addr" version.
   5782      *
   5783      * See OP_MUL_LONG for an explanation.
   5784      *
   5785      * We get a little tight on registers, so to avoid looking up &fp[A]
   5786      * again we stuff it into rINST.
   5787      */
   5788     /* mul-long/2addr vA, vB */
   5789     mov     r9, rINST, lsr #8           @ r9<- A+
   5790     mov     r1, rINST, lsr #12          @ r1<- B
   5791     and     r9, r9, #15
   5792     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5793     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
   5794     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5795     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
   5796     mul     ip, r2, r1                  @  ip<- ZxW
   5797     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
   5798     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
   5799     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
   5800     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5801     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
   5802     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5803     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
   5804     GOTO_OPCODE(ip)                     @ jump to next instruction
   5805 
   5806 /* ------------------------------ */
   5807     .balign 64
   5808 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
   5809 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
   5810 /* File: armv5te/binopWide2addr.S */
   5811     /*
   5812      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5813      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5814      * This could be an ARM instruction or a function call.  (If the result
   5815      * comes back in a register other than r0, you can override "result".)
   5816      *
   5817      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5818      * vCC (r1).  Useful for integer division and modulus.
   5819      *
   5820      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5821      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5822      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5823      *      rem-double/2addr
   5824      */
   5825     /* binop/2addr vA, vB */
   5826     mov     r9, rINST, lsr #8           @ r9<- A+
   5827     mov     r1, rINST, lsr #12          @ r1<- B
   5828     and     r9, r9, #15
   5829     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5830     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5831     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5832     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5833     .if 1
   5834     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5835     beq     common_errDivideByZero
   5836     .endif
   5837     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5838 
   5839                                @ optional op; may set condition codes
   5840     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   5841     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5842     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5843     GOTO_OPCODE(ip)                     @ jump to next instruction
   5844     /* 12-15 instructions */
   5845 
   5846 
   5847 /* ------------------------------ */
   5848     .balign 64
   5849 .L_OP_REM_LONG_2ADDR: /* 0xbf */
   5850 /* File: armv5te/OP_REM_LONG_2ADDR.S */
   5851 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
   5852 /* File: armv5te/binopWide2addr.S */
   5853     /*
   5854      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5855      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5856      * This could be an ARM instruction or a function call.  (If the result
   5857      * comes back in a register other than r0, you can override "result".)
   5858      *
   5859      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5860      * vCC (r1).  Useful for integer division and modulus.
   5861      *
   5862      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5863      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5864      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5865      *      rem-double/2addr
   5866      */
   5867     /* binop/2addr vA, vB */
   5868     mov     r9, rINST, lsr #8           @ r9<- A+
   5869     mov     r1, rINST, lsr #12          @ r1<- B
   5870     and     r9, r9, #15
   5871     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5872     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5873     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5874     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5875     .if 1
   5876     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5877     beq     common_errDivideByZero
   5878     .endif
   5879     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5880 
   5881                                @ optional op; may set condition codes
   5882     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   5883     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5884     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
   5885     GOTO_OPCODE(ip)                     @ jump to next instruction
   5886     /* 12-15 instructions */
   5887 
   5888 
   5889 /* ------------------------------ */
   5890     .balign 64
   5891 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
   5892 /* File: armv5te/OP_AND_LONG_2ADDR.S */
   5893 /* File: armv5te/binopWide2addr.S */
   5894     /*
   5895      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5896      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5897      * This could be an ARM instruction or a function call.  (If the result
   5898      * comes back in a register other than r0, you can override "result".)
   5899      *
   5900      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5901      * vCC (r1).  Useful for integer division and modulus.
   5902      *
   5903      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5904      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5905      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5906      *      rem-double/2addr
   5907      */
   5908     /* binop/2addr vA, vB */
   5909     mov     r9, rINST, lsr #8           @ r9<- A+
   5910     mov     r1, rINST, lsr #12          @ r1<- B
   5911     and     r9, r9, #15
   5912     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5913     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5914     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5915     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5916     .if 0
   5917     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5918     beq     common_errDivideByZero
   5919     .endif
   5920     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5921 
   5922     and     r0, r0, r2                           @ optional op; may set condition codes
   5923     and     r1, r1, r3                              @ result<- op, r0-r3 changed
   5924     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5925     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5926     GOTO_OPCODE(ip)                     @ jump to next instruction
   5927     /* 12-15 instructions */
   5928 
   5929 
   5930 /* ------------------------------ */
   5931     .balign 64
   5932 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
   5933 /* File: armv5te/OP_OR_LONG_2ADDR.S */
   5934 /* File: armv5te/binopWide2addr.S */
   5935     /*
   5936      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5937      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5938      * This could be an ARM instruction or a function call.  (If the result
   5939      * comes back in a register other than r0, you can override "result".)
   5940      *
   5941      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5942      * vCC (r1).  Useful for integer division and modulus.
   5943      *
   5944      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5945      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5946      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5947      *      rem-double/2addr
   5948      */
   5949     /* binop/2addr vA, vB */
   5950     mov     r9, rINST, lsr #8           @ r9<- A+
   5951     mov     r1, rINST, lsr #12          @ r1<- B
   5952     and     r9, r9, #15
   5953     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5954     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5955     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5956     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5957     .if 0
   5958     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5959     beq     common_errDivideByZero
   5960     .endif
   5961     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5962 
   5963     orr     r0, r0, r2                           @ optional op; may set condition codes
   5964     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
   5965     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5966     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5967     GOTO_OPCODE(ip)                     @ jump to next instruction
   5968     /* 12-15 instructions */
   5969 
   5970 
   5971 /* ------------------------------ */
   5972     .balign 64
   5973 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
   5974 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
   5975 /* File: armv5te/binopWide2addr.S */
   5976     /*
   5977      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5978      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5979      * This could be an ARM instruction or a function call.  (If the result
   5980      * comes back in a register other than r0, you can override "result".)
   5981      *
   5982      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5983      * vCC (r1).  Useful for integer division and modulus.
   5984      *
   5985      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5986      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5987      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5988      *      rem-double/2addr
   5989      */
   5990     /* binop/2addr vA, vB */
   5991     mov     r9, rINST, lsr #8           @ r9<- A+
   5992     mov     r1, rINST, lsr #12          @ r1<- B
   5993     and     r9, r9, #15
   5994     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5995     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5996     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5997     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5998     .if 0
   5999     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6000     beq     common_errDivideByZero
   6001     .endif
   6002     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6003 
   6004     eor     r0, r0, r2                           @ optional op; may set condition codes
   6005     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
   6006     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6007     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6008     GOTO_OPCODE(ip)                     @ jump to next instruction
   6009     /* 12-15 instructions */
   6010 
   6011 
   6012 /* ------------------------------ */
   6013     .balign 64
   6014 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
   6015 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
   6016     /*
   6017      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6018      * 32-bit shift distance.
   6019      */
   6020     /* shl-long/2addr vA, vB */
   6021     mov     r9, rINST, lsr #8           @ r9<- A+
   6022     mov     r3, rINST, lsr #12          @ r3<- B
   6023     and     r9, r9, #15
   6024     GET_VREG(r2, r3)                    @ r2<- vB
   6025     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6026     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6027     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6028 
   6029     mov     r1, r1, asl r2              @  r1<- r1 << r2
   6030     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6031     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
   6032     subs    ip, r2, #32                 @  ip<- r2 - 32
   6033     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6034     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
   6035     mov     r0, r0, asl r2              @  r0<- r0 << r2
   6036     b       .LOP_SHL_LONG_2ADDR_finish
   6037 
   6038 /* ------------------------------ */
   6039     .balign 64
   6040 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
   6041 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
   6042     /*
   6043      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6044      * 32-bit shift distance.
   6045      */
   6046     /* shr-long/2addr vA, vB */
   6047     mov     r9, rINST, lsr #8           @ r9<- A+
   6048     mov     r3, rINST, lsr #12          @ r3<- B
   6049     and     r9, r9, #15
   6050     GET_VREG(r2, r3)                    @ r2<- vB
   6051     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6052     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6053     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6054 
   6055     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   6056     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6057     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   6058     subs    ip, r2, #32                 @  ip<- r2 - 32
   6059     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6060     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
   6061     mov     r1, r1, asr r2              @  r1<- r1 >> r2
   6062     b       .LOP_SHR_LONG_2ADDR_finish
   6063 
   6064 /* ------------------------------ */
   6065     .balign 64
   6066 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
   6067 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
   6068     /*
   6069      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6070      * 32-bit shift distance.
   6071      */
   6072     /* ushr-long/2addr vA, vB */
   6073     mov     r9, rINST, lsr #8           @ r9<- A+
   6074     mov     r3, rINST, lsr #12          @ r3<- B
   6075     and     r9, r9, #15
   6076     GET_VREG(r2, r3)                    @ r2<- vB
   6077     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6078     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6079     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6080 
   6081     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   6082     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6083     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   6084     subs    ip, r2, #32                 @  ip<- r2 - 32
   6085     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6086     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
   6087     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
   6088     b       .LOP_USHR_LONG_2ADDR_finish
   6089 
   6090 /* ------------------------------ */
   6091     .balign 64
   6092 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
   6093 /* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
   6094 /* File: arm-vfp/fbinop2addr.S */
   6095     /*
   6096      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6097      * an "instr" line that specifies an instruction that performs
   6098      * "s2 = s0 op s1".
   6099      *
   6100      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6101      */
   6102     /* binop/2addr vA, vB */
   6103     mov     r3, rINST, lsr #12          @ r3<- B
   6104     mov     r9, rINST, lsr #8           @ r9<- A+
   6105     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6106     and     r9, r9, #15                 @ r9<- A
   6107     flds    s1, [r3]                    @ s1<- vB
   6108     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6109     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6110     flds    s0, [r9]                    @ s0<- vA
   6111 
   6112     fadds   s2, s0, s1                              @ s2<- op
   6113     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6114     fsts    s2, [r9]                    @ vAA<- s2
   6115     GOTO_OPCODE(ip)                     @ jump to next instruction
   6116 
   6117 
   6118 /* ------------------------------ */
   6119     .balign 64
   6120 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
   6121 /* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
   6122 /* File: arm-vfp/fbinop2addr.S */
   6123     /*
   6124      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6125      * an "instr" line that specifies an instruction that performs
   6126      * "s2 = s0 op s1".
   6127      *
   6128      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6129      */
   6130     /* binop/2addr vA, vB */
   6131     mov     r3, rINST, lsr #12          @ r3<- B
   6132     mov     r9, rINST, lsr #8           @ r9<- A+
   6133     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6134     and     r9, r9, #15                 @ r9<- A
   6135     flds    s1, [r3]                    @ s1<- vB
   6136     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6137     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6138     flds    s0, [r9]                    @ s0<- vA
   6139 
   6140     fsubs   s2, s0, s1                              @ s2<- op
   6141     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6142     fsts    s2, [r9]                    @ vAA<- s2
   6143     GOTO_OPCODE(ip)                     @ jump to next instruction
   6144 
   6145 
   6146 /* ------------------------------ */
   6147     .balign 64
   6148 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
   6149 /* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
   6150 /* File: arm-vfp/fbinop2addr.S */
   6151     /*
   6152      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6153      * an "instr" line that specifies an instruction that performs
   6154      * "s2 = s0 op s1".
   6155      *
   6156      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6157      */
   6158     /* binop/2addr vA, vB */
   6159     mov     r3, rINST, lsr #12          @ r3<- B
   6160     mov     r9, rINST, lsr #8           @ r9<- A+
   6161     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6162     and     r9, r9, #15                 @ r9<- A
   6163     flds    s1, [r3]                    @ s1<- vB
   6164     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6165     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6166     flds    s0, [r9]                    @ s0<- vA
   6167 
   6168     fmuls   s2, s0, s1                              @ s2<- op
   6169     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6170     fsts    s2, [r9]                    @ vAA<- s2
   6171     GOTO_OPCODE(ip)                     @ jump to next instruction
   6172 
   6173 
   6174 /* ------------------------------ */
   6175     .balign 64
   6176 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
   6177 /* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
   6178 /* File: arm-vfp/fbinop2addr.S */
   6179     /*
   6180      * Generic 32-bit floating point "/2addr" binary operation.  Provide
   6181      * an "instr" line that specifies an instruction that performs
   6182      * "s2 = s0 op s1".
   6183      *
   6184      * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
   6185      */
   6186     /* binop/2addr vA, vB */
   6187     mov     r3, rINST, lsr #12          @ r3<- B
   6188     mov     r9, rINST, lsr #8           @ r9<- A+
   6189     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6190     and     r9, r9, #15                 @ r9<- A
   6191     flds    s1, [r3]                    @ s1<- vB
   6192     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6193     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6194     flds    s0, [r9]                    @ s0<- vA
   6195 
   6196     fdivs   s2, s0, s1                              @ s2<- op
   6197     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6198     fsts    s2, [r9]                    @ vAA<- s2
   6199     GOTO_OPCODE(ip)                     @ jump to next instruction
   6200 
   6201 
   6202 /* ------------------------------ */
   6203     .balign 64
   6204 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
   6205 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
   6206 /* EABI doesn't define a float remainder function, but libm does */
   6207 /* File: armv5te/binop2addr.S */
   6208     /*
   6209      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6210      * that specifies an instruction that performs "result = r0 op r1".
   6211      * This could be an ARM instruction or a function call.  (If the result
   6212      * comes back in a register other than r0, you can override "result".)
   6213      *
   6214      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6215      * vCC (r1).  Useful for integer division and modulus.
   6216      *
   6217      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6218      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6219      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6220      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6221      */
   6222     /* binop/2addr vA, vB */
   6223     mov     r9, rINST, lsr #8           @ r9<- A+
   6224     mov     r3, rINST, lsr #12          @ r3<- B
   6225     and     r9, r9, #15
   6226     GET_VREG(r1, r3)                    @ r1<- vB
   6227     GET_VREG(r0, r9)                    @ r0<- vA
   6228     .if 0
   6229     cmp     r1, #0                      @ is second operand zero?
   6230     beq     common_errDivideByZero
   6231     .endif
   6232     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6233 
   6234                                @ optional op; may set condition codes
   6235     bl      fmodf                              @ r0<- op, r0-r3 changed
   6236     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6237     SET_VREG(r0, r9)               @ vAA<- r0
   6238     GOTO_OPCODE(ip)                     @ jump to next instruction
   6239     /* 10-13 instructions */
   6240 
   6241 
   6242 /* ------------------------------ */
   6243     .balign 64
   6244 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
   6245 /* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
   6246 /* File: arm-vfp/fbinopWide2addr.S */
   6247     /*
   6248      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6249      * an "instr" line that specifies an instruction that performs
   6250      * "d2 = d0 op d1".
   6251      *
   6252      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6253      *      div-double/2addr
   6254      */
   6255     /* binop/2addr vA, vB */
   6256     mov     r3, rINST, lsr #12          @ r3<- B
   6257     mov     r9, rINST, lsr #8           @ r9<- A+
   6258     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6259     and     r9, r9, #15                 @ r9<- A
   6260     fldd    d1, [r3]                    @ d1<- vB
   6261     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6262     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6263     fldd    d0, [r9]                    @ d0<- vA
   6264 
   6265     faddd   d2, d0, d1                              @ d2<- op
   6266     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6267     fstd    d2, [r9]                    @ vAA<- d2
   6268     GOTO_OPCODE(ip)                     @ jump to next instruction
   6269 
   6270 
   6271 /* ------------------------------ */
   6272     .balign 64
   6273 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
   6274 /* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
   6275 /* File: arm-vfp/fbinopWide2addr.S */
   6276     /*
   6277      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6278      * an "instr" line that specifies an instruction that performs
   6279      * "d2 = d0 op d1".
   6280      *
   6281      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6282      *      div-double/2addr
   6283      */
   6284     /* binop/2addr vA, vB */
   6285     mov     r3, rINST, lsr #12          @ r3<- B
   6286     mov     r9, rINST, lsr #8           @ r9<- A+
   6287     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6288     and     r9, r9, #15                 @ r9<- A
   6289     fldd    d1, [r3]                    @ d1<- vB
   6290     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6291     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6292     fldd    d0, [r9]                    @ d0<- vA
   6293 
   6294     fsubd   d2, d0, d1                              @ d2<- op
   6295     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6296     fstd    d2, [r9]                    @ vAA<- d2
   6297     GOTO_OPCODE(ip)                     @ jump to next instruction
   6298 
   6299 
   6300 /* ------------------------------ */
   6301     .balign 64
   6302 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
   6303 /* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
   6304 /* File: arm-vfp/fbinopWide2addr.S */
   6305     /*
   6306      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6307      * an "instr" line that specifies an instruction that performs
   6308      * "d2 = d0 op d1".
   6309      *
   6310      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6311      *      div-double/2addr
   6312      */
   6313     /* binop/2addr vA, vB */
   6314     mov     r3, rINST, lsr #12          @ r3<- B
   6315     mov     r9, rINST, lsr #8           @ r9<- A+
   6316     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6317     and     r9, r9, #15                 @ r9<- A
   6318     fldd    d1, [r3]                    @ d1<- vB
   6319     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6320     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6321     fldd    d0, [r9]                    @ d0<- vA
   6322 
   6323     fmuld   d2, d0, d1                              @ d2<- op
   6324     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6325     fstd    d2, [r9]                    @ vAA<- d2
   6326     GOTO_OPCODE(ip)                     @ jump to next instruction
   6327 
   6328 
   6329 /* ------------------------------ */
   6330     .balign 64
   6331 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
   6332 /* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
   6333 /* File: arm-vfp/fbinopWide2addr.S */
   6334     /*
   6335      * Generic 64-bit floating point "/2addr" binary operation.  Provide
   6336      * an "instr" line that specifies an instruction that performs
   6337      * "d2 = d0 op d1".
   6338      *
   6339      * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
   6340      *      div-double/2addr
   6341      */
   6342     /* binop/2addr vA, vB */
   6343     mov     r3, rINST, lsr #12          @ r3<- B
   6344     mov     r9, rINST, lsr #8           @ r9<- A+
   6345     VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
   6346     and     r9, r9, #15                 @ r9<- A
   6347     fldd    d1, [r3]                    @ d1<- vB
   6348     VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
   6349     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6350     fldd    d0, [r9]                    @ d0<- vA
   6351 
   6352     fdivd   d2, d0, d1                              @ d2<- op
   6353     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6354     fstd    d2, [r9]                    @ vAA<- d2
   6355     GOTO_OPCODE(ip)                     @ jump to next instruction
   6356 
   6357 
   6358 /* ------------------------------ */
   6359     .balign 64
   6360 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
   6361 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
   6362 /* EABI doesn't define a double remainder function, but libm does */
   6363 /* File: armv5te/binopWide2addr.S */
   6364     /*
   6365      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6366      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6367      * This could be an ARM instruction or a function call.  (If the result
   6368      * comes back in a register other than r0, you can override "result".)
   6369      *
   6370      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6371      * vCC (r1).  Useful for integer division and modulus.
   6372      *
   6373      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6374      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6375      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6376      *      rem-double/2addr
   6377      */
   6378     /* binop/2addr vA, vB */
   6379     mov     r9, rINST, lsr #8           @ r9<- A+
   6380     mov     r1, rINST, lsr #12          @ r1<- B
   6381     and     r9, r9, #15
   6382     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6383     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6384     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6385     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6386     .if 0
   6387     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6388     beq     common_errDivideByZero
   6389     .endif
   6390     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6391 
   6392                                @ optional op; may set condition codes
   6393     bl      fmod                              @ result<- op, r0-r3 changed
   6394     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6395     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6396     GOTO_OPCODE(ip)                     @ jump to next instruction
   6397     /* 12-15 instructions */
   6398 
   6399 
   6400 /* ------------------------------ */
   6401     .balign 64
   6402 .L_OP_ADD_INT_LIT16: /* 0xd0 */
   6403 /* File: armv5te/OP_ADD_INT_LIT16.S */
   6404 /* File: armv5te/binopLit16.S */
   6405     /*
   6406      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6407      * that specifies an instruction that performs "result = r0 op r1".
   6408      * This could be an ARM instruction or a function call.  (If the result
   6409      * comes back in a register other than r0, you can override "result".)
   6410      *
   6411      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6412      * vCC (r1).  Useful for integer division and modulus.
   6413      *
   6414      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6415      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6416      */
   6417     /* binop/lit16 vA, vB, #+CCCC */
   6418     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6419     mov     r2, rINST, lsr #12          @ r2<- B
   6420     mov     r9, rINST, lsr #8           @ r9<- A+
   6421     GET_VREG(r0, r2)                    @ r0<- vB
   6422     and     r9, r9, #15
   6423     .if 0
   6424     cmp     r1, #0                      @ is second operand zero?
   6425     beq     common_errDivideByZero
   6426     .endif
   6427     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6428 
   6429     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6430     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6431     SET_VREG(r0, r9)               @ vAA<- r0
   6432     GOTO_OPCODE(ip)                     @ jump to next instruction
   6433     /* 10-13 instructions */
   6434 
   6435 
   6436 /* ------------------------------ */
   6437     .balign 64
   6438 .L_OP_RSUB_INT: /* 0xd1 */
   6439 /* File: armv5te/OP_RSUB_INT.S */
   6440 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
   6441 /* File: armv5te/binopLit16.S */
   6442     /*
   6443      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6444      * that specifies an instruction that performs "result = r0 op r1".
   6445      * This could be an ARM instruction or a function call.  (If the result
   6446      * comes back in a register other than r0, you can override "result".)
   6447      *
   6448      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6449      * vCC (r1).  Useful for integer division and modulus.
   6450      *
   6451      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6452      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6453      */
   6454     /* binop/lit16 vA, vB, #+CCCC */
   6455     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6456     mov     r2, rINST, lsr #12          @ r2<- B
   6457     mov     r9, rINST, lsr #8           @ r9<- A+
   6458     GET_VREG(r0, r2)                    @ r0<- vB
   6459     and     r9, r9, #15
   6460     .if 0
   6461     cmp     r1, #0                      @ is second operand zero?
   6462     beq     common_errDivideByZero
   6463     .endif
   6464     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6465 
   6466     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6467     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6468     SET_VREG(r0, r9)               @ vAA<- r0
   6469     GOTO_OPCODE(ip)                     @ jump to next instruction
   6470     /* 10-13 instructions */
   6471 
   6472 
   6473 /* ------------------------------ */
   6474     .balign 64
   6475 .L_OP_MUL_INT_LIT16: /* 0xd2 */
   6476 /* File: armv5te/OP_MUL_INT_LIT16.S */
   6477 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   6478 /* File: armv5te/binopLit16.S */
   6479     /*
   6480      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6481      * that specifies an instruction that performs "result = r0 op r1".
   6482      * This could be an ARM instruction or a function call.  (If the result
   6483      * comes back in a register other than r0, you can override "result".)
   6484      *
   6485      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6486      * vCC (r1).  Useful for integer division and modulus.
   6487      *
   6488      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6489      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6490      */
   6491     /* binop/lit16 vA, vB, #+CCCC */
   6492     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6493     mov     r2, rINST, lsr #12          @ r2<- B
   6494     mov     r9, rINST, lsr #8           @ r9<- A+
   6495     GET_VREG(r0, r2)                    @ r0<- vB
   6496     and     r9, r9, #15
   6497     .if 0
   6498     cmp     r1, #0                      @ is second operand zero?
   6499     beq     common_errDivideByZero
   6500     .endif
   6501     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6502 
   6503     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   6504     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6505     SET_VREG(r0, r9)               @ vAA<- r0
   6506     GOTO_OPCODE(ip)                     @ jump to next instruction
   6507     /* 10-13 instructions */
   6508 
   6509 
   6510 /* ------------------------------ */
   6511     .balign 64
   6512 .L_OP_DIV_INT_LIT16: /* 0xd3 */
   6513 /* File: armv5te/OP_DIV_INT_LIT16.S */
   6514 /* File: armv5te/binopLit16.S */
   6515     /*
   6516      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6517      * that specifies an instruction that performs "result = r0 op r1".
   6518      * This could be an ARM instruction or a function call.  (If the result
   6519      * comes back in a register other than r0, you can override "result".)
   6520      *
   6521      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6522      * vCC (r1).  Useful for integer division and modulus.
   6523      *
   6524      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6525      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6526      */
   6527     /* binop/lit16 vA, vB, #+CCCC */
   6528     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6529     mov     r2, rINST, lsr #12          @ r2<- B
   6530     mov     r9, rINST, lsr #8           @ r9<- A+
   6531     GET_VREG(r0, r2)                    @ r0<- vB
   6532     and     r9, r9, #15
   6533     .if 1
   6534     cmp     r1, #0                      @ is second operand zero?
   6535     beq     common_errDivideByZero
   6536     .endif
   6537     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6538 
   6539     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   6540     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6541     SET_VREG(r0, r9)               @ vAA<- r0
   6542     GOTO_OPCODE(ip)                     @ jump to next instruction
   6543     /* 10-13 instructions */
   6544 
   6545 
   6546 /* ------------------------------ */
   6547     .balign 64
   6548 .L_OP_REM_INT_LIT16: /* 0xd4 */
   6549 /* File: armv5te/OP_REM_INT_LIT16.S */
   6550 /* idivmod returns quotient in r0 and remainder in r1 */
   6551 /* File: armv5te/binopLit16.S */
   6552     /*
   6553      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6554      * that specifies an instruction that performs "result = r0 op r1".
   6555      * This could be an ARM instruction or a function call.  (If the result
   6556      * comes back in a register other than r0, you can override "result".)
   6557      *
   6558      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6559      * vCC (r1).  Useful for integer division and modulus.
   6560      *
   6561      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6562      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6563      */
   6564     /* binop/lit16 vA, vB, #+CCCC */
   6565     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6566     mov     r2, rINST, lsr #12          @ r2<- B
   6567     mov     r9, rINST, lsr #8           @ r9<- A+
   6568     GET_VREG(r0, r2)                    @ r0<- vB
   6569     and     r9, r9, #15
   6570     .if 1
   6571     cmp     r1, #0                      @ is second operand zero?
   6572     beq     common_errDivideByZero
   6573     .endif
   6574     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6575 
   6576     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   6577     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6578     SET_VREG(r1, r9)               @ vAA<- r1
   6579     GOTO_OPCODE(ip)                     @ jump to next instruction
   6580     /* 10-13 instructions */
   6581 
   6582 
   6583 /* ------------------------------ */
   6584     .balign 64
   6585 .L_OP_AND_INT_LIT16: /* 0xd5 */
   6586 /* File: armv5te/OP_AND_INT_LIT16.S */
   6587 /* File: armv5te/binopLit16.S */
   6588     /*
   6589      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6590      * that specifies an instruction that performs "result = r0 op r1".
   6591      * This could be an ARM instruction or a function call.  (If the result
   6592      * comes back in a register other than r0, you can override "result".)
   6593      *
   6594      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6595      * vCC (r1).  Useful for integer division and modulus.
   6596      *
   6597      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6598      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6599      */
   6600     /* binop/lit16 vA, vB, #+CCCC */
   6601     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6602     mov     r2, rINST, lsr #12          @ r2<- B
   6603     mov     r9, rINST, lsr #8           @ r9<- A+
   6604     GET_VREG(r0, r2)                    @ r0<- vB
   6605     and     r9, r9, #15
   6606     .if 0
   6607     cmp     r1, #0                      @ is second operand zero?
   6608     beq     common_errDivideByZero
   6609     .endif
   6610     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6611 
   6612     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6613     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6614     SET_VREG(r0, r9)               @ vAA<- r0
   6615     GOTO_OPCODE(ip)                     @ jump to next instruction
   6616     /* 10-13 instructions */
   6617 
   6618 
   6619 /* ------------------------------ */
   6620     .balign 64
   6621 .L_OP_OR_INT_LIT16: /* 0xd6 */
   6622 /* File: armv5te/OP_OR_INT_LIT16.S */
   6623 /* File: armv5te/binopLit16.S */
   6624     /*
   6625      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6626      * that specifies an instruction that performs "result = r0 op r1".
   6627      * This could be an ARM instruction or a function call.  (If the result
   6628      * comes back in a register other than r0, you can override "result".)
   6629      *
   6630      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6631      * vCC (r1).  Useful for integer division and modulus.
   6632      *
   6633      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6634      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6635      */
   6636     /* binop/lit16 vA, vB, #+CCCC */
   6637     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6638     mov     r2, rINST, lsr #12          @ r2<- B
   6639     mov     r9, rINST, lsr #8           @ r9<- A+
   6640     GET_VREG(r0, r2)                    @ r0<- vB
   6641     and     r9, r9, #15
   6642     .if 0
   6643     cmp     r1, #0                      @ is second operand zero?
   6644     beq     common_errDivideByZero
   6645     .endif
   6646     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6647 
   6648     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6649     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6650     SET_VREG(r0, r9)               @ vAA<- r0
   6651     GOTO_OPCODE(ip)                     @ jump to next instruction
   6652     /* 10-13 instructions */
   6653 
   6654 
   6655 /* ------------------------------ */
   6656     .balign 64
   6657 .L_OP_XOR_INT_LIT16: /* 0xd7 */
   6658 /* File: armv5te/OP_XOR_INT_LIT16.S */
   6659 /* File: armv5te/binopLit16.S */
   6660     /*
   6661      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6662      * that specifies an instruction that performs "result = r0 op r1".
   6663      * This could be an ARM instruction or a function call.  (If the result
   6664      * comes back in a register other than r0, you can override "result".)
   6665      *
   6666      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6667      * vCC (r1).  Useful for integer division and modulus.
   6668      *
   6669      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6670      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6671      */
   6672     /* binop/lit16 vA, vB, #+CCCC */
   6673     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6674     mov     r2, rINST, lsr #12          @ r2<- B
   6675     mov     r9, rINST, lsr #8           @ r9<- A+
   6676     GET_VREG(r0, r2)                    @ r0<- vB
   6677     and     r9, r9, #15
   6678     .if 0
   6679     cmp     r1, #0                      @ is second operand zero?
   6680     beq     common_errDivideByZero
   6681     .endif
   6682     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6683 
   6684     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6685     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6686     SET_VREG(r0, r9)               @ vAA<- r0
   6687     GOTO_OPCODE(ip)                     @ jump to next instruction
   6688     /* 10-13 instructions */
   6689 
   6690 
   6691 /* ------------------------------ */
   6692     .balign 64
   6693 .L_OP_ADD_INT_LIT8: /* 0xd8 */
   6694 /* File: armv5te/OP_ADD_INT_LIT8.S */
   6695 /* File: armv5te/binopLit8.S */
   6696     /*
   6697      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6698      * that specifies an instruction that performs "result = r0 op r1".
   6699      * This could be an ARM instruction or a function call.  (If the result
   6700      * comes back in a register other than r0, you can override "result".)
   6701      *
   6702      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6703      * vCC (r1).  Useful for integer division and modulus.
   6704      *
   6705      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6706      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6707      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6708      */
   6709     /* binop/lit8 vAA, vBB, #+CC */
   6710     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6711     mov     r9, rINST, lsr #8           @ r9<- AA
   6712     and     r2, r3, #255                @ r2<- BB
   6713     GET_VREG(r0, r2)                    @ r0<- vBB
   6714     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6715     .if 0
   6716     @cmp     r1, #0                      @ is second operand zero?
   6717     beq     common_errDivideByZero
   6718     .endif
   6719     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6720 
   6721                                @ optional op; may set condition codes
   6722     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6723     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6724     SET_VREG(r0, r9)               @ vAA<- r0
   6725     GOTO_OPCODE(ip)                     @ jump to next instruction
   6726     /* 10-12 instructions */
   6727 
   6728 
   6729 /* ------------------------------ */
   6730     .balign 64
   6731 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
   6732 /* File: armv5te/OP_RSUB_INT_LIT8.S */
   6733 /* File: armv5te/binopLit8.S */
   6734     /*
   6735      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6736      * that specifies an instruction that performs "result = r0 op r1".
   6737      * This could be an ARM instruction or a function call.  (If the result
   6738      * comes back in a register other than r0, you can override "result".)
   6739      *
   6740      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6741      * vCC (r1).  Useful for integer division and modulus.
   6742      *
   6743      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6744      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6745      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6746      */
   6747     /* binop/lit8 vAA, vBB, #+CC */
   6748     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6749     mov     r9, rINST, lsr #8           @ r9<- AA
   6750     and     r2, r3, #255                @ r2<- BB
   6751     GET_VREG(r0, r2)                    @ r0<- vBB
   6752     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6753     .if 0
   6754     @cmp     r1, #0                      @ is second operand zero?
   6755     beq     common_errDivideByZero
   6756     .endif
   6757     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6758 
   6759                                @ optional op; may set condition codes
   6760     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6761     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6762     SET_VREG(r0, r9)               @ vAA<- r0
   6763     GOTO_OPCODE(ip)                     @ jump to next instruction
   6764     /* 10-12 instructions */
   6765 
   6766 
   6767 /* ------------------------------ */
   6768     .balign 64
   6769 .L_OP_MUL_INT_LIT8: /* 0xda */
   6770 /* File: armv5te/OP_MUL_INT_LIT8.S */
   6771 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   6772 /* File: armv5te/binopLit8.S */
   6773     /*
   6774      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6775      * that specifies an instruction that performs "result = r0 op r1".
   6776      * This could be an ARM instruction or a function call.  (If the result
   6777      * comes back in a register other than r0, you can override "result".)
   6778      *
   6779      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6780      * vCC (r1).  Useful for integer division and modulus.
   6781      *
   6782      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6783      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6784      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6785      */
   6786     /* binop/lit8 vAA, vBB, #+CC */
   6787     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6788     mov     r9, rINST, lsr #8           @ r9<- AA
   6789     and     r2, r3, #255                @ r2<- BB
   6790     GET_VREG(r0, r2)                    @ r0<- vBB
   6791     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6792     .if 0
   6793     @cmp     r1, #0                      @ is second operand zero?
   6794     beq     common_errDivideByZero
   6795     .endif
   6796     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6797 
   6798                                @ optional op; may set condition codes
   6799     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   6800     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6801     SET_VREG(r0, r9)               @ vAA<- r0
   6802     GOTO_OPCODE(ip)                     @ jump to next instruction
   6803     /* 10-12 instructions */
   6804 
   6805 
   6806 /* ------------------------------ */
   6807     .balign 64
   6808 .L_OP_DIV_INT_LIT8: /* 0xdb */
   6809 /* File: armv5te/OP_DIV_INT_LIT8.S */
   6810 /* File: armv5te/binopLit8.S */
   6811     /*
   6812      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6813      * that specifies an instruction that performs "result = r0 op r1".
   6814      * This could be an ARM instruction or a function call.  (If the result
   6815      * comes back in a register other than r0, you can override "result".)
   6816      *
   6817      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6818      * vCC (r1).  Useful for integer division and modulus.
   6819      *
   6820      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6821      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6822      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6823      */
   6824     /* binop/lit8 vAA, vBB, #+CC */
   6825     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6826     mov     r9, rINST, lsr #8           @ r9<- AA
   6827     and     r2, r3, #255                @ r2<- BB
   6828     GET_VREG(r0, r2)                    @ r0<- vBB
   6829     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6830     .if 1
   6831     @cmp     r1, #0                      @ is second operand zero?
   6832     beq     common_errDivideByZero
   6833     .endif
   6834     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6835 
   6836                                @ optional op; may set condition codes
   6837     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   6838     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6839     SET_VREG(r0, r9)               @ vAA<- r0
   6840     GOTO_OPCODE(ip)                     @ jump to next instruction
   6841     /* 10-12 instructions */
   6842 
   6843 
   6844 /* ------------------------------ */
   6845     .balign 64
   6846 .L_OP_REM_INT_LIT8: /* 0xdc */
   6847 /* File: armv5te/OP_REM_INT_LIT8.S */
   6848 /* idivmod returns quotient in r0 and remainder in r1 */
   6849 /* File: armv5te/binopLit8.S */
   6850     /*
   6851      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6852      * that specifies an instruction that performs "result = r0 op r1".
   6853      * This could be an ARM instruction or a function call.  (If the result
   6854      * comes back in a register other than r0, you can override "result".)
   6855      *
   6856      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6857      * vCC (r1).  Useful for integer division and modulus.
   6858      *
   6859      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6860      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6861      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6862      */
   6863     /* binop/lit8 vAA, vBB, #+CC */
   6864     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6865     mov     r9, rINST, lsr #8           @ r9<- AA
   6866     and     r2, r3, #255                @ r2<- BB
   6867     GET_VREG(r0, r2)                    @ r0<- vBB
   6868     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6869     .if 1
   6870     @cmp     r1, #0                      @ is second operand zero?
   6871     beq     common_errDivideByZero
   6872     .endif
   6873     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6874 
   6875                                @ optional op; may set condition codes
   6876     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   6877     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6878     SET_VREG(r1, r9)               @ vAA<- r1
   6879     GOTO_OPCODE(ip)                     @ jump to next instruction
   6880     /* 10-12 instructions */
   6881 
   6882 
   6883 /* ------------------------------ */
   6884     .balign 64
   6885 .L_OP_AND_INT_LIT8: /* 0xdd */
   6886 /* File: armv5te/OP_AND_INT_LIT8.S */
   6887 /* File: armv5te/binopLit8.S */
   6888     /*
   6889      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6890      * that specifies an instruction that performs "result = r0 op r1".
   6891      * This could be an ARM instruction or a function call.  (If the result
   6892      * comes back in a register other than r0, you can override "result".)
   6893      *
   6894      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6895      * vCC (r1).  Useful for integer division and modulus.
   6896      *
   6897      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6898      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6899      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6900      */
   6901     /* binop/lit8 vAA, vBB, #+CC */
   6902     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6903     mov     r9, rINST, lsr #8           @ r9<- AA
   6904     and     r2, r3, #255                @ r2<- BB
   6905     GET_VREG(r0, r2)                    @ r0<- vBB
   6906     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6907     .if 0
   6908     @cmp     r1, #0                      @ is second operand zero?
   6909     beq     common_errDivideByZero
   6910     .endif
   6911     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6912 
   6913                                @ optional op; may set condition codes
   6914     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6915     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6916     SET_VREG(r0, r9)               @ vAA<- r0
   6917     GOTO_OPCODE(ip)                     @ jump to next instruction
   6918     /* 10-12 instructions */
   6919 
   6920 
   6921 /* ------------------------------ */
   6922     .balign 64
   6923 .L_OP_OR_INT_LIT8: /* 0xde */
   6924 /* File: armv5te/OP_OR_INT_LIT8.S */
   6925 /* File: armv5te/binopLit8.S */
   6926     /*
   6927      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6928      * that specifies an instruction that performs "result = r0 op r1".
   6929      * This could be an ARM instruction or a function call.  (If the result
   6930      * comes back in a register other than r0, you can override "result".)
   6931      *
   6932      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6933      * vCC (r1).  Useful for integer division and modulus.
   6934      *
   6935      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6936      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6937      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6938      */
   6939     /* binop/lit8 vAA, vBB, #+CC */
   6940     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6941     mov     r9, rINST, lsr #8           @ r9<- AA
   6942     and     r2, r3, #255                @ r2<- BB
   6943     GET_VREG(r0, r2)                    @ r0<- vBB
   6944     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6945     .if 0
   6946     @cmp     r1, #0                      @ is second operand zero?
   6947     beq     common_errDivideByZero
   6948     .endif
   6949     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6950 
   6951                                @ optional op; may set condition codes
   6952     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6953     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6954     SET_VREG(r0, r9)               @ vAA<- r0
   6955     GOTO_OPCODE(ip)                     @ jump to next instruction
   6956     /* 10-12 instructions */
   6957 
   6958 
   6959 /* ------------------------------ */
   6960     .balign 64
   6961 .L_OP_XOR_INT_LIT8: /* 0xdf */
   6962 /* File: armv5te/OP_XOR_INT_LIT8.S */
   6963 /* File: armv5te/binopLit8.S */
   6964     /*
   6965      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   6966      * that specifies an instruction that performs "result = r0 op r1".
   6967      * This could be an ARM instruction or a function call.  (If the result
   6968      * comes back in a register other than r0, you can override "result".)
   6969      *
   6970      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6971      * vCC (r1).  Useful for integer division and modulus.
   6972      *
   6973      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   6974      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   6975      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   6976      */
   6977     /* binop/lit8 vAA, vBB, #+CC */
   6978     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   6979     mov     r9, rINST, lsr #8           @ r9<- AA
   6980     and     r2, r3, #255                @ r2<- BB
   6981     GET_VREG(r0, r2)                    @ r0<- vBB
   6982     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   6983     .if 0
   6984     @cmp     r1, #0                      @ is second operand zero?
   6985     beq     common_errDivideByZero
   6986     .endif
   6987     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6988 
   6989                                @ optional op; may set condition codes
   6990     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6991     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6992     SET_VREG(r0, r9)               @ vAA<- r0
   6993     GOTO_OPCODE(ip)                     @ jump to next instruction
   6994     /* 10-12 instructions */
   6995 
   6996 
   6997 /* ------------------------------ */
   6998     .balign 64
   6999 .L_OP_SHL_INT_LIT8: /* 0xe0 */
   7000 /* File: armv5te/OP_SHL_INT_LIT8.S */
   7001 /* File: armv5te/binopLit8.S */
   7002     /*
   7003      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7004      * that specifies an instruction that performs "result = r0 op r1".
   7005      * This could be an ARM instruction or a function call.  (If the result
   7006      * comes back in a register other than r0, you can override "result".)
   7007      *
   7008      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7009      * vCC (r1).  Useful for integer division and modulus.
   7010      *
   7011      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7012      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7013      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7014      */
   7015     /* binop/lit8 vAA, vBB, #+CC */
   7016     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7017     mov     r9, rINST, lsr #8           @ r9<- AA
   7018     and     r2, r3, #255                @ r2<- BB
   7019     GET_VREG(r0, r2)                    @ r0<- vBB
   7020     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7021     .if 0
   7022     @cmp     r1, #0                      @ is second operand zero?
   7023     beq     common_errDivideByZero
   7024     .endif
   7025     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7026 
   7027     and     r1, r1, #31                           @ optional op; may set condition codes
   7028     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   7029     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7030     SET_VREG(r0, r9)               @ vAA<- r0
   7031     GOTO_OPCODE(ip)                     @ jump to next instruction
   7032     /* 10-12 instructions */
   7033 
   7034 
   7035 /* ------------------------------ */
   7036     .balign 64
   7037 .L_OP_SHR_INT_LIT8: /* 0xe1 */
   7038 /* File: armv5te/OP_SHR_INT_LIT8.S */
   7039 /* File: armv5te/binopLit8.S */
   7040     /*
   7041      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7042      * that specifies an instruction that performs "result = r0 op r1".
   7043      * This could be an ARM instruction or a function call.  (If the result
   7044      * comes back in a register other than r0, you can override "result".)
   7045      *
   7046      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7047      * vCC (r1).  Useful for integer division and modulus.
   7048      *
   7049      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7050      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7051      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7052      */
   7053     /* binop/lit8 vAA, vBB, #+CC */
   7054     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7055     mov     r9, rINST, lsr #8           @ r9<- AA
   7056     and     r2, r3, #255                @ r2<- BB
   7057     GET_VREG(r0, r2)                    @ r0<- vBB
   7058     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7059     .if 0
   7060     @cmp     r1, #0                      @ is second operand zero?
   7061     beq     common_errDivideByZero
   7062     .endif
   7063     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7064 
   7065     and     r1, r1, #31                           @ optional op; may set condition codes
   7066     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   7067     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7068     SET_VREG(r0, r9)               @ vAA<- r0
   7069     GOTO_OPCODE(ip)                     @ jump to next instruction
   7070     /* 10-12 instructions */
   7071 
   7072 
   7073 /* ------------------------------ */
   7074     .balign 64
   7075 .L_OP_USHR_INT_LIT8: /* 0xe2 */
   7076 /* File: armv5te/OP_USHR_INT_LIT8.S */
   7077 /* File: armv5te/binopLit8.S */
   7078     /*
   7079      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7080      * that specifies an instruction that performs "result = r0 op r1".
   7081      * This could be an ARM instruction or a function call.  (If the result
   7082      * comes back in a register other than r0, you can override "result".)
   7083      *
   7084      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7085      * vCC (r1).  Useful for integer division and modulus.
   7086      *
   7087      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7088      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7089      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7090      */
   7091     /* binop/lit8 vAA, vBB, #+CC */
   7092     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7093     mov     r9, rINST, lsr #8           @ r9<- AA
   7094     and     r2, r3, #255                @ r2<- BB
   7095     GET_VREG(r0, r2)                    @ r0<- vBB
   7096     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7097     .if 0
   7098     @cmp     r1, #0                      @ is second operand zero?
   7099     beq     common_errDivideByZero
   7100     .endif
   7101     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7102 
   7103     and     r1, r1, #31                           @ optional op; may set condition codes
   7104     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   7105     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7106     SET_VREG(r0, r9)               @ vAA<- r0
   7107     GOTO_OPCODE(ip)                     @ jump to next instruction
   7108     /* 10-12 instructions */
   7109 
   7110 
   7111 /* ------------------------------ */
   7112     .balign 64
   7113 .L_OP_IGET_VOLATILE: /* 0xe3 */
   7114 /* File: armv5te/OP_IGET_VOLATILE.S */
   7115 /* File: armv5te/OP_IGET.S */
   7116     /*
   7117      * General 32-bit instance field get.
   7118      *
   7119      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   7120      */
   7121     /* op vA, vB, field@CCCC */
   7122     mov     r0, rINST, lsr #12          @ r0<- B
   7123     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7124     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7125     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7126     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7127     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7128     cmp     r0, #0                      @ is resolved entry null?
   7129     bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
   7130 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7131     EXPORT_PC()                         @ resolve() could throw
   7132     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7133     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7134     cmp     r0, #0
   7135     bne     .LOP_IGET_VOLATILE_finish
   7136     b       common_exceptionThrown
   7137 
   7138 
   7139 /* ------------------------------ */
   7140     .balign 64
   7141 .L_OP_IPUT_VOLATILE: /* 0xe4 */
   7142 /* File: armv5te/OP_IPUT_VOLATILE.S */
   7143 /* File: armv5te/OP_IPUT.S */
   7144     /*
   7145      * General 32-bit instance field put.
   7146      *
   7147      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   7148      */
   7149     /* op vA, vB, field@CCCC */
   7150     mov     r0, rINST, lsr #12          @ r0<- B
   7151     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7152     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7153     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7154     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7155     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7156     cmp     r0, #0                      @ is resolved entry null?
   7157     bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
   7158 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7159     EXPORT_PC()                         @ resolve() could throw
   7160     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7161     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7162     cmp     r0, #0                      @ success?
   7163     bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
   7164     b       common_exceptionThrown
   7165 
   7166 
   7167 /* ------------------------------ */
   7168     .balign 64
   7169 .L_OP_SGET_VOLATILE: /* 0xe5 */
   7170 /* File: armv5te/OP_SGET_VOLATILE.S */
   7171 /* File: armv5te/OP_SGET.S */
   7172     /*
   7173      * General 32-bit SGET handler.
   7174      *
   7175      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   7176      */
   7177     /* op vAA, field@BBBB */
   7178     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7179     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7180     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7181     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7182     cmp     r0, #0                      @ is resolved entry null?
   7183     beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
   7184 .LOP_SGET_VOLATILE_finish: @ field ptr in r0
   7185     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   7186     SMP_DMB                            @ acquiring load
   7187     mov     r2, rINST, lsr #8           @ r2<- AA
   7188     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7189     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   7190     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7191     GOTO_OPCODE(ip)                     @ jump to next instruction
   7192 
   7193 
   7194 /* ------------------------------ */
   7195     .balign 64
   7196 .L_OP_SPUT_VOLATILE: /* 0xe6 */
   7197 /* File: armv5te/OP_SPUT_VOLATILE.S */
   7198 /* File: armv5te/OP_SPUT.S */
   7199     /*
   7200      * General 32-bit SPUT handler.
   7201      *
   7202      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   7203      */
   7204     /* op vAA, field@BBBB */
   7205     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7206     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7207     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7208     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7209     cmp     r0, #0                      @ is resolved entry null?
   7210     beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
   7211 .LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
   7212     mov     r2, rINST, lsr #8           @ r2<- AA
   7213     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7214     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   7215     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7216     SMP_DMB                            @ releasing store
   7217     str     r1, [r0, #offStaticField_value] @ field<- vAA
   7218     GOTO_OPCODE(ip)                     @ jump to next instruction
   7219 
   7220 
   7221 /* ------------------------------ */
   7222     .balign 64
   7223 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
   7224 /* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
   7225 /* File: armv5te/OP_IGET.S */
   7226     /*
   7227      * General 32-bit instance field get.
   7228      *
   7229      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   7230      */
   7231     /* op vA, vB, field@CCCC */
   7232     mov     r0, rINST, lsr #12          @ r0<- B
   7233     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7234     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7235     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7236     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7237     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7238     cmp     r0, #0                      @ is resolved entry null?
   7239     bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
   7240 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7241     EXPORT_PC()                         @ resolve() could throw
   7242     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7243     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7244     cmp     r0, #0
   7245     bne     .LOP_IGET_OBJECT_VOLATILE_finish
   7246     b       common_exceptionThrown
   7247 
   7248 
   7249 /* ------------------------------ */
   7250     .balign 64
   7251 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
   7252 /* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
   7253 /* File: armv5te/OP_IGET_WIDE.S */
   7254     /*
   7255      * Wide 32-bit instance field get.
   7256      */
   7257     /* iget-wide vA, vB, field@CCCC */
   7258     mov     r0, rINST, lsr #12          @ r0<- B
   7259     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7260     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7261     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   7262     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7263     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7264     cmp     r0, #0                      @ is resolved entry null?
   7265     bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
   7266 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   7267     EXPORT_PC()                         @ resolve() could throw
   7268     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7269     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7270     cmp     r0, #0
   7271     bne     .LOP_IGET_WIDE_VOLATILE_finish
   7272     b       common_exceptionThrown
   7273 
   7274 
   7275 /* ------------------------------ */
   7276     .balign 64
   7277 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
   7278 /* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
   7279 /* File: armv5te/OP_IPUT_WIDE.S */
   7280     /* iput-wide vA, vB, field@CCCC */
   7281     mov     r0, rINST, lsr #12          @ r0<- B
   7282     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7283     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7284     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   7285     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7286     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7287     cmp     r0, #0                      @ is resolved entry null?
   7288     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
   7289 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   7290     EXPORT_PC()                         @ resolve() could throw
   7291     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7292     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7293     cmp     r0, #0                      @ success?
   7294     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
   7295     b       common_exceptionThrown
   7296 
   7297 
   7298 /* ------------------------------ */
   7299     .balign 64
   7300 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
   7301 /* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
   7302 /* File: armv5te/OP_SGET_WIDE.S */
   7303     /*
   7304      * 64-bit SGET handler.
   7305      */
   7306     /* sget-wide vAA, field@BBBB */
   7307     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7308     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7309     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7310     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7311     cmp     r0, #0                      @ is resolved entry null?
   7312     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
   7313 .LOP_SGET_WIDE_VOLATILE_finish:
   7314     mov     r9, rINST, lsr #8           @ r9<- AA
   7315     .if 1
   7316     add     r0, r0, #offStaticField_value @ r0<- pointer to data
   7317     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   7318     .else
   7319     ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
   7320     .endif
   7321     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   7322     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7323     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   7324     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7325     GOTO_OPCODE(ip)                     @ jump to next instruction
   7326 
   7327 
   7328 /* ------------------------------ */
   7329     .balign 64
   7330 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
   7331 /* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
   7332 /* File: armv5te/OP_SPUT_WIDE.S */
   7333     /*
   7334      * 64-bit SPUT handler.
   7335      */
   7336     /* sput-wide vAA, field@BBBB */
   7337     ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
   7338     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7339     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
   7340     mov     r9, rINST, lsr #8           @ r9<- AA
   7341     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
   7342     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   7343     cmp     r2, #0                      @ is resolved entry null?
   7344     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
   7345 .LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
   7346     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7347     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   7348     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   7349     .if 1
   7350     add     r2, r2, #offStaticField_value @ r2<- pointer to data
   7351     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   7352     .else
   7353     strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
   7354     .endif
   7355     GOTO_OPCODE(r10)                    @ jump to next instruction
   7356 
   7357 
   7358 /* ------------------------------ */
   7359     .balign 64
   7360 .L_OP_BREAKPOINT: /* 0xec */
   7361 /* File: armv5te/OP_BREAKPOINT.S */
   7362 /* File: armv5te/unused.S */
   7363     bl      common_abort
   7364 
   7365 
   7366 /* ------------------------------ */
   7367     .balign 64
   7368 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
   7369 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
   7370     /*
   7371      * Handle a throw-verification-error instruction.  This throws an
   7372      * exception for an error discovered during verification.  The
   7373      * exception is indicated by AA, with some detail provided by BBBB.
   7374      */
   7375     /* op AA, ref@BBBB */
   7376     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
   7377     FETCH(r2, 1)                        @ r2<- BBBB
   7378     EXPORT_PC()                         @ export the PC
   7379     mov     r1, rINST, lsr #8           @ r1<- AA
   7380     bl      dvmThrowVerificationError   @ always throws
   7381     b       common_exceptionThrown      @ handle exception
   7382 
   7383 /* ------------------------------ */
   7384     .balign 64
   7385 .L_OP_EXECUTE_INLINE: /* 0xee */
   7386 /* File: armv5te/OP_EXECUTE_INLINE.S */
   7387     /*
   7388      * Execute a "native inline" instruction.
   7389      *
   7390      * We need to call an InlineOp4Func:
   7391      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
   7392      *
   7393      * The first four args are in r0-r3, pointer to return value storage
   7394      * is on the stack.  The function's return value is a flag that tells
   7395      * us if an exception was thrown.
   7396      */
   7397     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
   7398     FETCH(r10, 1)                       @ r10<- BBBB
   7399     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
   7400     EXPORT_PC()                         @ can throw
   7401     sub     sp, sp, #8                  @ make room for arg, +64 bit align
   7402     mov     r0, rINST, lsr #12          @ r0<- B
   7403     str     r1, [sp]                    @ push &glue->retval
   7404     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
   7405     add     sp, sp, #8                  @ pop stack
   7406     cmp     r0, #0                      @ test boolean result of inline
   7407     beq     common_exceptionThrown      @ returned false, handle exception
   7408     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7409     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7410     GOTO_OPCODE(ip)                     @ jump to next instruction
   7411 
   7412 /* ------------------------------ */
   7413     .balign 64
   7414 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
   7415 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
   7416     /*
   7417      * Execute a "native inline" instruction, using "/range" semantics.
   7418      * Same idea as execute-inline, but we get the args differently.
   7419      *
   7420      * We need to call an InlineOp4Func:
   7421      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
   7422      *
   7423      * The first four args are in r0-r3, pointer to return value storage
   7424      * is on the stack.  The function's return value is a flag that tells
   7425      * us if an exception was thrown.
   7426      */
   7427     /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
   7428     FETCH(r10, 1)                       @ r10<- BBBB
   7429     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
   7430     EXPORT_PC()                         @ can throw
   7431     sub     sp, sp, #8                  @ make room for arg, +64 bit align
   7432     mov     r0, rINST, lsr #8           @ r0<- AA
   7433     str     r1, [sp]                    @ push &glue->retval
   7434     bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
   7435     add     sp, sp, #8                  @ pop stack
   7436     cmp     r0, #0                      @ test boolean result of inline
   7437     beq     common_exceptionThrown      @ returned false, handle exception
   7438     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7439     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7440     GOTO_OPCODE(ip)                     @ jump to next instruction
   7441 
   7442 /* ------------------------------ */
   7443     .balign 64
   7444 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
   7445 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
   7446     /*
   7447      * invoke-direct-empty is a no-op in a "standard" interpreter.
   7448      */
   7449     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   7450     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
   7451     GOTO_OPCODE(ip)                     @ execute it
   7452 
   7453 /* ------------------------------ */
   7454     .balign 64
   7455 .L_OP_UNUSED_F1: /* 0xf1 */
   7456 /* File: armv5te/OP_UNUSED_F1.S */
   7457 /* File: armv5te/unused.S */
   7458     bl      common_abort
   7459 
   7460 
   7461 /* ------------------------------ */
   7462     .balign 64
   7463 .L_OP_IGET_QUICK: /* 0xf2 */
   7464 /* File: armv5te/OP_IGET_QUICK.S */
   7465     /* For: iget-quick, iget-object-quick */
   7466     /* op vA, vB, offset@CCCC */
   7467     mov     r2, rINST, lsr #12          @ r2<- B
   7468     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7469     FETCH(r1, 1)                        @ r1<- field byte offset
   7470     cmp     r3, #0                      @ check object for null
   7471     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7472     beq     common_errNullObject        @ object was null
   7473     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
   7474     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7475     and     r2, r2, #15
   7476     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7477     SET_VREG(r0, r2)                    @ fp[A]<- r0
   7478     GOTO_OPCODE(ip)                     @ jump to next instruction
   7479 
   7480 /* ------------------------------ */
   7481     .balign 64
   7482 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
   7483 /* File: armv5te/OP_IGET_WIDE_QUICK.S */
   7484     /* iget-wide-quick vA, vB, offset@CCCC */
   7485     mov     r2, rINST, lsr #12          @ r2<- B
   7486     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7487     FETCH(ip, 1)                        @ ip<- field byte offset
   7488     cmp     r3, #0                      @ check object for null
   7489     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7490     beq     common_errNullObject        @ object was null
   7491     ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
   7492     and     r2, r2, #15
   7493     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7494     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   7495     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7496     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   7497     GOTO_OPCODE(ip)                     @ jump to next instruction
   7498 
   7499 /* ------------------------------ */
   7500     .balign 64
   7501 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
   7502 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
   7503 /* File: armv5te/OP_IGET_QUICK.S */
   7504     /* For: iget-quick, iget-object-quick */
   7505     /* op vA, vB, offset@CCCC */
   7506     mov     r2, rINST, lsr #12          @ r2<- B
   7507     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7508     FETCH(r1, 1)                        @ r1<- field byte offset
   7509     cmp     r3, #0                      @ check object for null
   7510     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7511     beq     common_errNullObject        @ object was null
   7512     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
   7513     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7514     and     r2, r2, #15
   7515     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7516     SET_VREG(r0, r2)                    @ fp[A]<- r0
   7517     GOTO_OPCODE(ip)                     @ jump to next instruction
   7518 
   7519 
   7520 /* ------------------------------ */
   7521     .balign 64
   7522 .L_OP_IPUT_QUICK: /* 0xf5 */
   7523 /* File: armv5te/OP_IPUT_QUICK.S */
   7524     /* For: iput-quick */
   7525     /* op vA, vB, offset@CCCC */
   7526     mov     r2, rINST, lsr #12          @ r2<- B
   7527     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
   7528     FETCH(r1, 1)                        @ r1<- field byte offset
   7529     cmp     r3, #0                      @ check object for null
   7530     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7531     beq     common_errNullObject        @ object was null
   7532     and     r2, r2, #15
   7533     GET_VREG(r0, r2)                    @ r0<- fp[A]
   7534     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7535     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
   7536     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7537     GOTO_OPCODE(ip)                     @ jump to next instruction
   7538 
   7539 /* ------------------------------ */
   7540     .balign 64
   7541 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
   7542 /* File: armv5te/OP_IPUT_WIDE_QUICK.S */
   7543     /* iput-wide-quick vA, vB, offset@CCCC */
   7544     mov     r0, rINST, lsr #8           @ r0<- A(+)
   7545     mov     r1, rINST, lsr #12          @ r1<- B
   7546     and     r0, r0, #15
   7547     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
   7548     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
   7549     cmp     r2, #0                      @ check object for null
   7550     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
   7551     beq     common_errNullObject        @ object was null
   7552     FETCH(r3, 1)                        @ r3<- field byte offset
   7553     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7554     strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
   7555     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7556     GOTO_OPCODE(ip)                     @ jump to next instruction
   7557 
   7558 /* ------------------------------ */
   7559     .balign 64
   7560 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
   7561 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
   7562     /* For: iput-object-quick */
   7563     /* op vA, vB, offset@CCCC */
   7564     mov     r2, rINST, lsr #12          @ r2<- B
   7565     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
   7566     FETCH(r1, 1)                        @ r1<- field byte offset
   7567     cmp     r3, #0                      @ check object for null
   7568     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7569     beq     common_errNullObject        @ object was null
   7570     and     r2, r2, #15
   7571     GET_VREG(r0, r2)                    @ r0<- fp[A]
   7572     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   7573     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7574     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
   7575     cmp     r0, #0
   7576     strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
   7577     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7578     GOTO_OPCODE(ip)                     @ jump to next instruction
   7579 
   7580 /* ------------------------------ */
   7581     .balign 64
   7582 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
   7583 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
   7584     /*
   7585      * Handle an optimized virtual method call.
   7586      *
   7587      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
   7588      */
   7589     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7590     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7591     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
   7592     FETCH(r1, 1)                        @ r1<- BBBB
   7593     .if     (!0)
   7594     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
   7595     .endif
   7596     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
   7597     cmp     r2, #0                      @ is "this" null?
   7598     beq     common_errNullObject        @ null "this", throw exception
   7599     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
   7600     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
   7601     EXPORT_PC()                         @ invoke must export
   7602     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
   7603     bl      common_invokeMethodNoRange @ continue on
   7604 
   7605 /* ------------------------------ */
   7606     .balign 64
   7607 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
   7608 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
   7609 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
   7610     /*
   7611      * Handle an optimized virtual method call.
   7612      *
   7613      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
   7614      */
   7615     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7616     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7617     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
   7618     FETCH(r1, 1)                        @ r1<- BBBB
   7619     .if     (!1)
   7620     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
   7621     .endif
   7622     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
   7623     cmp     r2, #0                      @ is "this" null?
   7624     beq     common_errNullObject        @ null "this", throw exception
   7625     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
   7626     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
   7627     EXPORT_PC()                         @ invoke must export
   7628     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
   7629     bl      common_invokeMethodRange @ continue on
   7630 
   7631 
   7632 /* ------------------------------ */
   7633     .balign 64
   7634 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
   7635 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
   7636     /*
   7637      * Handle an optimized "super" method call.
   7638      *
   7639      * for: [opt] invoke-super-quick, invoke-super-quick/range
   7640      */
   7641     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7642     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7643     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   7644     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7645     .if     (!0)
   7646     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   7647     .endif
   7648     FETCH(r1, 1)                        @ r1<- BBBB
   7649     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
   7650     EXPORT_PC()                         @ must export for invoke
   7651     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
   7652     GET_VREG(r3, r10)                   @ r3<- "this"
   7653     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
   7654     cmp     r3, #0                      @ null "this" ref?
   7655     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
   7656     beq     common_errNullObject        @ "this" is null, throw exception
   7657     bl      common_invokeMethodNoRange @ continue on
   7658 
   7659 /* ------------------------------ */
   7660     .balign 64
   7661 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
   7662 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
   7663 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
   7664     /*
   7665      * Handle an optimized "super" method call.
   7666      *
   7667      * for: [opt] invoke-super-quick, invoke-super-quick/range
   7668      */
   7669     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7670     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7671     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   7672     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7673     .if     (!1)
   7674     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   7675     .endif
   7676     FETCH(r1, 1)                        @ r1<- BBBB
   7677     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
   7678     EXPORT_PC()                         @ must export for invoke
   7679     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
   7680     GET_VREG(r3, r10)                   @ r3<- "this"
   7681     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
   7682     cmp     r3, #0                      @ null "this" ref?
   7683     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
   7684     beq     common_errNullObject        @ "this" is null, throw exception
   7685     bl      common_invokeMethodRange @ continue on
   7686 
   7687 
   7688 /* ------------------------------ */
   7689     .balign 64
   7690 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
   7691 /* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
   7692 /* File: armv5te/OP_IPUT_OBJECT.S */
   7693     /*
   7694      * 32-bit instance field put.
   7695      *
   7696      * for: iput-object, iput-object-volatile
   7697      */
   7698     /* op vA, vB, field@CCCC */
   7699     mov     r0, rINST, lsr #12          @ r0<- B
   7700     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7701     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7702     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7703     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7704     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7705     cmp     r0, #0                      @ is resolved entry null?
   7706     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
   7707 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7708     EXPORT_PC()                         @ resolve() could throw
   7709     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7710     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7711     cmp     r0, #0                      @ success?
   7712     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
   7713     b       common_exceptionThrown
   7714 
   7715 
   7716 /* ------------------------------ */
   7717     .balign 64
   7718 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
   7719 /* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
   7720 /* File: armv5te/OP_SGET.S */
   7721     /*
   7722      * General 32-bit SGET handler.
   7723      *
   7724      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   7725      */
   7726     /* op vAA, field@BBBB */
   7727     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7728     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7729     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7730     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7731     cmp     r0, #0                      @ is resolved entry null?
   7732     beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
   7733 .LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
   7734     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   7735     SMP_DMB                            @ acquiring load
   7736     mov     r2, rINST, lsr #8           @ r2<- AA
   7737     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7738     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   7739     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7740     GOTO_OPCODE(ip)                     @ jump to next instruction
   7741 
   7742 
   7743 /* ------------------------------ */
   7744     .balign 64
   7745 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
   7746 /* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
   7747 /* File: armv5te/OP_SPUT_OBJECT.S */
   7748     /*
   7749      * 32-bit SPUT handler for objects
   7750      *
   7751      * for: sput-object, sput-object-volatile
   7752      */
   7753     /* op vAA, field@BBBB */
   7754     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7755     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7756     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7757     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7758     cmp     r0, #0                      @ is resolved entry null?
   7759     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
   7760     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
   7761     EXPORT_PC()                         @ resolve() could throw, so export now
   7762     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
   7763     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   7764     cmp     r0, #0                      @ success?
   7765     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
   7766     b       common_exceptionThrown      @ no, handle exception
   7767 
   7768 
   7769 
   7770 /* ------------------------------ */
   7771     .balign 64
   7772 .L_OP_UNUSED_FF: /* 0xff */
   7773 /* File: armv5te/OP_UNUSED_FF.S */
   7774 /* File: armv5te/unused.S */
   7775     bl      common_abort
   7776 
   7777 
   7778 
   7779     .balign 64
   7780     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
   7781     .global dvmAsmInstructionEnd
   7782 dvmAsmInstructionEnd:
   7783 
   7784 /*
   7785  * ===========================================================================
   7786  *  Sister implementations
   7787  * ===========================================================================
   7788  */
   7789     .global dvmAsmSisterStart
   7790     .type   dvmAsmSisterStart, %function
   7791     .text
   7792     .balign 4
   7793 dvmAsmSisterStart:
   7794 
   7795 /* continuation for OP_CONST_STRING */
   7796 
   7797     /*
   7798      * Continuation if the String has not yet been resolved.
   7799      *  r1: BBBB (String ref)
   7800      *  r9: target register
   7801      */
   7802 .LOP_CONST_STRING_resolve:
   7803     EXPORT_PC()
   7804     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   7805     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7806     bl      dvmResolveString            @ r0<- String reference
   7807     cmp     r0, #0                      @ failed?
   7808     beq     common_exceptionThrown      @ yup, handle the exception
   7809     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7810     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7811     SET_VREG(r0, r9)                    @ vAA<- r0
   7812     GOTO_OPCODE(ip)                     @ jump to next instruction
   7813 
   7814 /* continuation for OP_CONST_STRING_JUMBO */
   7815 
   7816     /*
   7817      * Continuation if the String has not yet been resolved.
   7818      *  r1: BBBBBBBB (String ref)
   7819      *  r9: target register
   7820      */
   7821 .LOP_CONST_STRING_JUMBO_resolve:
   7822     EXPORT_PC()
   7823     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   7824     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7825     bl      dvmResolveString            @ r0<- String reference
   7826     cmp     r0, #0                      @ failed?
   7827     beq     common_exceptionThrown      @ yup, handle the exception
   7828     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7829     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7830     SET_VREG(r0, r9)                    @ vAA<- r0
   7831     GOTO_OPCODE(ip)                     @ jump to next instruction
   7832 
   7833 /* continuation for OP_CONST_CLASS */
   7834 
   7835     /*
   7836      * Continuation if the Class has not yet been resolved.
   7837      *  r1: BBBB (Class ref)
   7838      *  r9: target register
   7839      */
   7840 .LOP_CONST_CLASS_resolve:
   7841     EXPORT_PC()
   7842     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   7843     mov     r2, #1                      @ r2<- true
   7844     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7845     bl      dvmResolveClass             @ r0<- Class reference
   7846     cmp     r0, #0                      @ failed?
   7847     beq     common_exceptionThrown      @ yup, handle the exception
   7848     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7849     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7850     SET_VREG(r0, r9)                    @ vAA<- r0
   7851     GOTO_OPCODE(ip)                     @ jump to next instruction
   7852 
   7853 /* continuation for OP_CHECK_CAST */
   7854 
   7855     /*
   7856      * Trivial test failed, need to perform full check.  This is common.
   7857      *  r0 holds obj->clazz
   7858      *  r1 holds class resolved from BBBB
   7859      *  r9 holds object
   7860      */
   7861 .LOP_CHECK_CAST_fullcheck:
   7862     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
   7863     cmp     r0, #0                      @ failed?
   7864     bne     .LOP_CHECK_CAST_okay            @ no, success
   7865 
   7866     @ A cast has failed.  We need to throw a ClassCastException with the
   7867     @ class of the object that failed to be cast.
   7868     EXPORT_PC()                         @ about to throw
   7869     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
   7870     ldr     r0, .LstrClassCastExceptionPtr
   7871     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
   7872     bl      dvmThrowExceptionWithClassMessage
   7873     b       common_exceptionThrown
   7874 
   7875     /*
   7876      * Resolution required.  This is the least-likely path.
   7877      *
   7878      *  r2 holds BBBB
   7879      *  r9 holds object
   7880      */
   7881 .LOP_CHECK_CAST_resolve:
   7882     EXPORT_PC()                         @ resolve() could throw
   7883     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   7884     mov     r1, r2                      @ r1<- BBBB
   7885     mov     r2, #0                      @ r2<- false
   7886     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   7887     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   7888     cmp     r0, #0                      @ got null?
   7889     beq     common_exceptionThrown      @ yes, handle exception
   7890     mov     r1, r0                      @ r1<- class resolved from BBB
   7891     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
   7892     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
   7893 
   7894 .LstrClassCastExceptionPtr:
   7895     .word   .LstrClassCastException
   7896 
   7897 /* continuation for OP_INSTANCE_OF */
   7898 
   7899     /*
   7900      * Trivial test failed, need to perform full check.  This is common.
   7901      *  r0 holds obj->clazz
   7902      *  r1 holds class resolved from BBBB
   7903      *  r9 holds A
   7904      */
   7905 .LOP_INSTANCE_OF_fullcheck:
   7906     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
   7907     @ fall through to OP_INSTANCE_OF_store
   7908 
   7909     /*
   7910      * r0 holds boolean result
   7911      * r9 holds A
   7912      */
   7913 .LOP_INSTANCE_OF_store:
   7914     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7915     SET_VREG(r0, r9)                    @ vA<- r0
   7916     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7917     GOTO_OPCODE(ip)                     @ jump to next instruction
   7918 
   7919     /*
   7920      * Trivial test succeeded, save and bail.
   7921      *  r9 holds A
   7922      */
   7923 .LOP_INSTANCE_OF_trivial:
   7924     mov     r0, #1                      @ indicate success
   7925     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
   7926     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7927     SET_VREG(r0, r9)                    @ vA<- r0
   7928     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7929     GOTO_OPCODE(ip)                     @ jump to next instruction
   7930 
   7931     /*
   7932      * Resolution required.  This is the least-likely path.
   7933      *
   7934      *  r3 holds BBBB
   7935      *  r9 holds A
   7936      */
   7937 .LOP_INSTANCE_OF_resolve:
   7938     EXPORT_PC()                         @ resolve() could throw
   7939     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
   7940     mov     r1, r3                      @ r1<- BBBB
   7941     mov     r2, #1                      @ r2<- true
   7942     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   7943     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   7944     cmp     r0, #0                      @ got null?
   7945     beq     common_exceptionThrown      @ yes, handle exception
   7946     mov     r1, r0                      @ r1<- class resolved from BBB
   7947     mov     r3, rINST, lsr #12          @ r3<- B
   7948     GET_VREG(r0, r3)                    @ r0<- vB (object)
   7949     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
   7950     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
   7951 
   7952 /* continuation for OP_NEW_INSTANCE */
   7953 
   7954     .balign 32                          @ minimize cache lines
   7955 .LOP_NEW_INSTANCE_finish: @ r0=new object
   7956     mov     r3, rINST, lsr #8           @ r3<- AA
   7957     cmp     r0, #0                      @ failed?
   7958     beq     common_exceptionThrown      @ yes, handle the exception
   7959     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7960     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7961     SET_VREG(r0, r3)                    @ vAA<- r0
   7962     GOTO_OPCODE(ip)                     @ jump to next instruction
   7963 
   7964     /*
   7965      * Class initialization required.
   7966      *
   7967      *  r0 holds class object
   7968      */
   7969 .LOP_NEW_INSTANCE_needinit:
   7970     mov     r9, r0                      @ save r0
   7971     bl      dvmInitClass                @ initialize class
   7972     cmp     r0, #0                      @ check boolean result
   7973     mov     r0, r9                      @ restore r0
   7974     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
   7975     b       common_exceptionThrown      @ failed, deal with init exception
   7976 
   7977     /*
   7978      * Resolution required.  This is the least-likely path.
   7979      *
   7980      *  r1 holds BBBB
   7981      */
   7982 .LOP_NEW_INSTANCE_resolve:
   7983     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   7984     mov     r2, #0                      @ r2<- false
   7985     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   7986     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   7987     cmp     r0, #0                      @ got null?
   7988     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
   7989     b       common_exceptionThrown      @ yes, handle exception
   7990 
   7991 .LstrInstantiationErrorPtr:
   7992     .word   .LstrInstantiationError
   7993 
   7994 /* continuation for OP_NEW_ARRAY */
   7995 
   7996 
   7997     /*
   7998      * Resolve class.  (This is an uncommon case.)
   7999      *
   8000      *  r1 holds array length
   8001      *  r2 holds class ref CCCC
   8002      */
   8003 .LOP_NEW_ARRAY_resolve:
   8004     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8005     mov     r9, r1                      @ r9<- length (save)
   8006     mov     r1, r2                      @ r1<- CCCC
   8007     mov     r2, #0                      @ r2<- false
   8008     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8009     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   8010     cmp     r0, #0                      @ got null?
   8011     mov     r1, r9                      @ r1<- length (restore)
   8012     beq     common_exceptionThrown      @ yes, handle exception
   8013     @ fall through to OP_NEW_ARRAY_finish
   8014 
   8015     /*
   8016      * Finish allocation.
   8017      *
   8018      *  r0 holds class
   8019      *  r1 holds array length
   8020      */
   8021 .LOP_NEW_ARRAY_finish:
   8022     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
   8023     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
   8024     cmp     r0, #0                      @ failed?
   8025     mov     r2, rINST, lsr #8           @ r2<- A+
   8026     beq     common_exceptionThrown      @ yes, handle the exception
   8027     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8028     and     r2, r2, #15                 @ r2<- A
   8029     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8030     SET_VREG(r0, r2)                    @ vA<- r0
   8031     GOTO_OPCODE(ip)                     @ jump to next instruction
   8032 
   8033 /* continuation for OP_FILLED_NEW_ARRAY */
   8034 
   8035     /*
   8036      * On entry:
   8037      *  r0 holds array class
   8038      *  r10 holds AA or BA
   8039      */
   8040 .LOP_FILLED_NEW_ARRAY_continue:
   8041     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
   8042     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
   8043     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
   8044     .if     0
   8045     mov     r1, r10                     @ r1<- AA (length)
   8046     .else
   8047     mov     r1, r10, lsr #4             @ r1<- B (length)
   8048     .endif
   8049     cmp     rINST, #'I'                 @ array of ints?
   8050     cmpne   rINST, #'L'                 @ array of objects?
   8051     cmpne   rINST, #'['                 @ array of arrays?
   8052     mov     r9, r1                      @ save length in r9
   8053     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
   8054     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
   8055     cmp     r0, #0                      @ null return?
   8056     beq     common_exceptionThrown      @ alloc failed, handle exception
   8057 
   8058     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
   8059     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
   8060     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
   8061     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
   8062     subs    r9, r9, #1                  @ length--, check for neg
   8063     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   8064     bmi     2f                          @ was zero, bail
   8065 
   8066     @ copy values from registers into the array
   8067     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
   8068     .if     0
   8069     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
   8070 1:  ldr     r3, [r2], #4                @ r3<- *r2++
   8071     subs    r9, r9, #1                  @ count--
   8072     str     r3, [r0], #4                @ *contents++ = vX
   8073     bpl     1b
   8074     @ continue at 2
   8075     .else
   8076     cmp     r9, #4                      @ length was initially 5?
   8077     and     r2, r10, #15                @ r2<- A
   8078     bne     1f                          @ <= 4 args, branch
   8079     GET_VREG(r3, r2)                    @ r3<- vA
   8080     sub     r9, r9, #1                  @ count--
   8081     str     r3, [r0, #16]               @ contents[4] = vA
   8082 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
   8083     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
   8084     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
   8085     subs    r9, r9, #1                  @ count--
   8086     str     r3, [r0], #4                @ *contents++ = vX
   8087     bpl     1b
   8088     @ continue at 2
   8089     .endif
   8090 
   8091 2:
   8092     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
   8093     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
   8094     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8095     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
   8096     cmp     r1, #'I'                         @ Is int array?
   8097     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
   8098     GOTO_OPCODE(ip)                          @ execute it
   8099 
   8100     /*
   8101      * Throw an exception indicating that we have not implemented this
   8102      * mode of filled-new-array.
   8103      */
   8104 .LOP_FILLED_NEW_ARRAY_notimpl:
   8105     ldr     r0, .L_strInternalError
   8106     ldr     r1, .L_strFilledNewArrayNotImpl
   8107     bl      dvmThrowException
   8108     b       common_exceptionThrown
   8109 
   8110     .if     (!0)                 @ define in one or the other, not both
   8111 .L_strFilledNewArrayNotImpl:
   8112     .word   .LstrFilledNewArrayNotImpl
   8113 .L_strInternalError:
   8114     .word   .LstrInternalError
   8115     .endif
   8116 
   8117 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
   8118 
   8119     /*
   8120      * On entry:
   8121      *  r0 holds array class
   8122      *  r10 holds AA or BA
   8123      */
   8124 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
   8125     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
   8126     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
   8127     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
   8128     .if     1
   8129     mov     r1, r10                     @ r1<- AA (length)
   8130     .else
   8131     mov     r1, r10, lsr #4             @ r1<- B (length)
   8132     .endif
   8133     cmp     rINST, #'I'                 @ array of ints?
   8134     cmpne   rINST, #'L'                 @ array of objects?
   8135     cmpne   rINST, #'['                 @ array of arrays?
   8136     mov     r9, r1                      @ save length in r9
   8137     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
   8138     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
   8139     cmp     r0, #0                      @ null return?
   8140     beq     common_exceptionThrown      @ alloc failed, handle exception
   8141 
   8142     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
   8143     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
   8144     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
   8145     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
   8146     subs    r9, r9, #1                  @ length--, check for neg
   8147     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   8148     bmi     2f                          @ was zero, bail
   8149 
   8150     @ copy values from registers into the array
   8151     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
   8152     .if     1
   8153     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
   8154 1:  ldr     r3, [r2], #4                @ r3<- *r2++
   8155     subs    r9, r9, #1                  @ count--
   8156     str     r3, [r0], #4                @ *contents++ = vX
   8157     bpl     1b
   8158     @ continue at 2
   8159     .else
   8160     cmp     r9, #4                      @ length was initially 5?
   8161     and     r2, r10, #15                @ r2<- A
   8162     bne     1f                          @ <= 4 args, branch
   8163     GET_VREG(r3, r2)                    @ r3<- vA
   8164     sub     r9, r9, #1                  @ count--
   8165     str     r3, [r0, #16]               @ contents[4] = vA
   8166 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
   8167     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
   8168     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
   8169     subs    r9, r9, #1                  @ count--
   8170     str     r3, [r0], #4                @ *contents++ = vX
   8171     bpl     1b
   8172     @ continue at 2
   8173     .endif
   8174 
   8175 2:
   8176     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
   8177     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
   8178     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8179     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
   8180     cmp     r1, #'I'                         @ Is int array?
   8181     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
   8182     GOTO_OPCODE(ip)                          @ execute it
   8183 
   8184     /*
   8185      * Throw an exception indicating that we have not implemented this
   8186      * mode of filled-new-array.
   8187      */
   8188 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
   8189     ldr     r0, .L_strInternalError
   8190     ldr     r1, .L_strFilledNewArrayNotImpl
   8191     bl      dvmThrowException
   8192     b       common_exceptionThrown
   8193 
   8194     .if     (!1)                 @ define in one or the other, not both
   8195 .L_strFilledNewArrayNotImpl:
   8196     .word   .LstrFilledNewArrayNotImpl
   8197 .L_strInternalError:
   8198     .word   .LstrInternalError
   8199     .endif
   8200 
   8201 /* continuation for OP_CMPL_FLOAT */
   8202 .LOP_CMPL_FLOAT_finish:
   8203     SET_VREG(r0, r9)                    @ vAA<- r0
   8204     GOTO_OPCODE(ip)                     @ jump to next instruction
   8205 
   8206 /* continuation for OP_CMPG_FLOAT */
   8207 .LOP_CMPG_FLOAT_finish:
   8208     SET_VREG(r0, r9)                    @ vAA<- r0
   8209     GOTO_OPCODE(ip)                     @ jump to next instruction
   8210 
   8211 /* continuation for OP_CMPL_DOUBLE */
   8212 .LOP_CMPL_DOUBLE_finish:
   8213     SET_VREG(r0, r9)                    @ vAA<- r0
   8214     GOTO_OPCODE(ip)                     @ jump to next instruction
   8215 
   8216 /* continuation for OP_CMPG_DOUBLE */
   8217 .LOP_CMPG_DOUBLE_finish:
   8218     SET_VREG(r0, r9)                    @ vAA<- r0
   8219     GOTO_OPCODE(ip)                     @ jump to next instruction
   8220 
   8221 /* continuation for OP_CMP_LONG */
   8222 
   8223 .LOP_CMP_LONG_less:
   8224     mvn     r1, #0                      @ r1<- -1
   8225     @ Want to cond code the next mov so we can avoid branch, but don't see it;
   8226     @ instead, we just replicate the tail end.
   8227     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8228     SET_VREG(r1, r9)                    @ vAA<- r1
   8229     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8230     GOTO_OPCODE(ip)                     @ jump to next instruction
   8231 
   8232 .LOP_CMP_LONG_greater:
   8233     mov     r1, #1                      @ r1<- 1
   8234     @ fall through to _finish
   8235 
   8236 .LOP_CMP_LONG_finish:
   8237     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8238     SET_VREG(r1, r9)                    @ vAA<- r1
   8239     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8240     GOTO_OPCODE(ip)                     @ jump to next instruction
   8241 
   8242 /* continuation for OP_AGET_WIDE */
   8243 
   8244 .LOP_AGET_WIDE_finish:
   8245     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8246     ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
   8247     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   8248     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8249     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
   8250     GOTO_OPCODE(ip)                     @ jump to next instruction
   8251 
   8252 /* continuation for OP_APUT_WIDE */
   8253 
   8254 .LOP_APUT_WIDE_finish:
   8255     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8256     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
   8257     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8258     strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
   8259     GOTO_OPCODE(ip)                     @ jump to next instruction
   8260 
   8261 /* continuation for OP_APUT_OBJECT */
   8262     /*
   8263      * On entry:
   8264      *  rINST = vBB (arrayObj)
   8265      *  r9 = vAA (obj)
   8266      *  r10 = offset into array (vBB + vCC * width)
   8267      */
   8268 .LOP_APUT_OBJECT_finish:
   8269     cmp     r9, #0                      @ storing null reference?
   8270     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
   8271     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
   8272     ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
   8273     bl      dvmCanPutArrayElement       @ test object type vs. array type
   8274     cmp     r0, #0                      @ okay?
   8275     beq     common_errArrayStore        @ no
   8276     mov     r1, rINST                   @ r1<- arrayObj
   8277     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8278     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
   8279     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
   8280     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8281     str     r9, [r10]                   @ vBB[vCC]<- vAA
   8282     strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
   8283     GOTO_OPCODE(ip)                     @ jump to next instruction
   8284 .LOP_APUT_OBJECT_skip_check:
   8285     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8286     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8287     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
   8288     GOTO_OPCODE(ip)                     @ jump to next instruction
   8289 
   8290 /* continuation for OP_IGET */
   8291 
   8292     /*
   8293      * Currently:
   8294      *  r0 holds resolved field
   8295      *  r9 holds object
   8296      */
   8297 .LOP_IGET_finish:
   8298     @bl      common_squeak0
   8299     cmp     r9, #0                      @ check object for null
   8300     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8301     beq     common_errNullObject        @ object was null
   8302     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8303     @ no-op                             @ acquiring load
   8304     mov     r2, rINST, lsr #8           @ r2<- A+
   8305     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8306     and     r2, r2, #15                 @ r2<- A
   8307     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8308     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8309     GOTO_OPCODE(ip)                     @ jump to next instruction
   8310 
   8311 /* continuation for OP_IGET_WIDE */
   8312 
   8313     /*
   8314      * Currently:
   8315      *  r0 holds resolved field
   8316      *  r9 holds object
   8317      */
   8318 .LOP_IGET_WIDE_finish:
   8319     cmp     r9, #0                      @ check object for null
   8320     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8321     beq     common_errNullObject        @ object was null
   8322     .if     0
   8323     add     r0, r9, r3                  @ r0<- address of field
   8324     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   8325     .else
   8326     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
   8327     .endif
   8328     mov     r2, rINST, lsr #8           @ r2<- A+
   8329     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8330     and     r2, r2, #15                 @ r2<- A
   8331     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   8332     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8333     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   8334     GOTO_OPCODE(ip)                     @ jump to next instruction
   8335 
   8336 /* continuation for OP_IGET_OBJECT */
   8337 
   8338     /*
   8339      * Currently:
   8340      *  r0 holds resolved field
   8341      *  r9 holds object
   8342      */
   8343 .LOP_IGET_OBJECT_finish:
   8344     @bl      common_squeak0
   8345     cmp     r9, #0                      @ check object for null
   8346     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8347     beq     common_errNullObject        @ object was null
   8348     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8349     @ no-op                             @ acquiring load
   8350     mov     r2, rINST, lsr #8           @ r2<- A+
   8351     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8352     and     r2, r2, #15                 @ r2<- A
   8353     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8354     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8355     GOTO_OPCODE(ip)                     @ jump to next instruction
   8356 
   8357 /* continuation for OP_IGET_BOOLEAN */
   8358 
   8359     /*
   8360      * Currently:
   8361      *  r0 holds resolved field
   8362      *  r9 holds object
   8363      */
   8364 .LOP_IGET_BOOLEAN_finish:
   8365     @bl      common_squeak1
   8366     cmp     r9, #0                      @ check object for null
   8367     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8368     beq     common_errNullObject        @ object was null
   8369     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8370     @ no-op                             @ acquiring load
   8371     mov     r2, rINST, lsr #8           @ r2<- A+
   8372     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8373     and     r2, r2, #15                 @ r2<- A
   8374     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8375     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8376     GOTO_OPCODE(ip)                     @ jump to next instruction
   8377 
   8378 /* continuation for OP_IGET_BYTE */
   8379 
   8380     /*
   8381      * Currently:
   8382      *  r0 holds resolved field
   8383      *  r9 holds object
   8384      */
   8385 .LOP_IGET_BYTE_finish:
   8386     @bl      common_squeak2
   8387     cmp     r9, #0                      @ check object for null
   8388     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8389     beq     common_errNullObject        @ object was null
   8390     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8391     @ no-op                             @ acquiring load
   8392     mov     r2, rINST, lsr #8           @ r2<- A+
   8393     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8394     and     r2, r2, #15                 @ r2<- A
   8395     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8396     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8397     GOTO_OPCODE(ip)                     @ jump to next instruction
   8398 
   8399 /* continuation for OP_IGET_CHAR */
   8400 
   8401     /*
   8402      * Currently:
   8403      *  r0 holds resolved field
   8404      *  r9 holds object
   8405      */
   8406 .LOP_IGET_CHAR_finish:
   8407     @bl      common_squeak3
   8408     cmp     r9, #0                      @ check object for null
   8409     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8410     beq     common_errNullObject        @ object was null
   8411     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8412     @ no-op                             @ acquiring load
   8413     mov     r2, rINST, lsr #8           @ r2<- A+
   8414     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8415     and     r2, r2, #15                 @ r2<- A
   8416     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8417     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8418     GOTO_OPCODE(ip)                     @ jump to next instruction
   8419 
   8420 /* continuation for OP_IGET_SHORT */
   8421 
   8422     /*
   8423      * Currently:
   8424      *  r0 holds resolved field
   8425      *  r9 holds object
   8426      */
   8427 .LOP_IGET_SHORT_finish:
   8428     @bl      common_squeak4
   8429     cmp     r9, #0                      @ check object for null
   8430     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8431     beq     common_errNullObject        @ object was null
   8432     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8433     @ no-op                             @ acquiring load
   8434     mov     r2, rINST, lsr #8           @ r2<- A+
   8435     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8436     and     r2, r2, #15                 @ r2<- A
   8437     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8438     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8439     GOTO_OPCODE(ip)                     @ jump to next instruction
   8440 
   8441 /* continuation for OP_IPUT */
   8442 
   8443     /*
   8444      * Currently:
   8445      *  r0 holds resolved field
   8446      *  r9 holds object
   8447      */
   8448 .LOP_IPUT_finish:
   8449     @bl      common_squeak0
   8450     mov     r1, rINST, lsr #8           @ r1<- A+
   8451     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8452     and     r1, r1, #15                 @ r1<- A
   8453     cmp     r9, #0                      @ check object for null
   8454     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8455     beq     common_errNullObject        @ object was null
   8456     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8457     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8458     @ no-op                             @ releasing store
   8459     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8460     GOTO_OPCODE(ip)                     @ jump to next instruction
   8461 
   8462 /* continuation for OP_IPUT_WIDE */
   8463 
   8464     /*
   8465      * Currently:
   8466      *  r0 holds resolved field
   8467      *  r9 holds object
   8468      */
   8469 .LOP_IPUT_WIDE_finish:
   8470     mov     r2, rINST, lsr #8           @ r2<- A+
   8471     cmp     r9, #0                      @ check object for null
   8472     and     r2, r2, #15                 @ r2<- A
   8473     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8474     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
   8475     beq     common_errNullObject        @ object was null
   8476     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8477     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
   8478     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   8479     .if     0
   8480     add     r2, r9, r3                  @ r2<- target address
   8481     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   8482     .else
   8483     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
   8484     .endif
   8485     GOTO_OPCODE(r10)                    @ jump to next instruction
   8486 
   8487 /* continuation for OP_IPUT_OBJECT */
   8488 
   8489     /*
   8490      * Currently:
   8491      *  r0 holds resolved field
   8492      *  r9 holds object
   8493      */
   8494 .LOP_IPUT_OBJECT_finish:
   8495     @bl      common_squeak0
   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     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8502     beq     common_errNullObject        @ object was null
   8503     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8504     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8505     @ no-op                             @ releasing store
   8506     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
   8507     cmp     r0, #0                      @ stored a null reference?
   8508     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
   8509     GOTO_OPCODE(ip)                     @ jump to next instruction
   8510 
   8511 /* continuation for OP_IPUT_BOOLEAN */
   8512 
   8513     /*
   8514      * Currently:
   8515      *  r0 holds resolved field
   8516      *  r9 holds object
   8517      */
   8518 .LOP_IPUT_BOOLEAN_finish:
   8519     @bl      common_squeak1
   8520     mov     r1, rINST, lsr #8           @ r1<- A+
   8521     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8522     and     r1, r1, #15                 @ r1<- A
   8523     cmp     r9, #0                      @ check object for null
   8524     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8525     beq     common_errNullObject        @ object was null
   8526     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8527     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8528     @ no-op                             @ releasing store
   8529     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8530     GOTO_OPCODE(ip)                     @ jump to next instruction
   8531 
   8532 /* continuation for OP_IPUT_BYTE */
   8533 
   8534     /*
   8535      * Currently:
   8536      *  r0 holds resolved field
   8537      *  r9 holds object
   8538      */
   8539 .LOP_IPUT_BYTE_finish:
   8540     @bl      common_squeak2
   8541     mov     r1, rINST, lsr #8           @ r1<- A+
   8542     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8543     and     r1, r1, #15                 @ r1<- A
   8544     cmp     r9, #0                      @ check object for null
   8545     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8546     beq     common_errNullObject        @ object was null
   8547     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8548     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8549     @ no-op                             @ releasing store
   8550     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8551     GOTO_OPCODE(ip)                     @ jump to next instruction
   8552 
   8553 /* continuation for OP_IPUT_CHAR */
   8554 
   8555     /*
   8556      * Currently:
   8557      *  r0 holds resolved field
   8558      *  r9 holds object
   8559      */
   8560 .LOP_IPUT_CHAR_finish:
   8561     @bl      common_squeak3
   8562     mov     r1, rINST, lsr #8           @ r1<- A+
   8563     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8564     and     r1, r1, #15                 @ r1<- A
   8565     cmp     r9, #0                      @ check object for null
   8566     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8567     beq     common_errNullObject        @ object was null
   8568     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8569     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8570     @ no-op                             @ releasing store
   8571     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8572     GOTO_OPCODE(ip)                     @ jump to next instruction
   8573 
   8574 /* continuation for OP_IPUT_SHORT */
   8575 
   8576     /*
   8577      * Currently:
   8578      *  r0 holds resolved field
   8579      *  r9 holds object
   8580      */
   8581 .LOP_IPUT_SHORT_finish:
   8582     @bl      common_squeak4
   8583     mov     r1, rINST, lsr #8           @ r1<- A+
   8584     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8585     and     r1, r1, #15                 @ r1<- A
   8586     cmp     r9, #0                      @ check object for null
   8587     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8588     beq     common_errNullObject        @ object was null
   8589     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8590     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8591     @ no-op                             @ releasing store
   8592     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8593     GOTO_OPCODE(ip)                     @ jump to next instruction
   8594 
   8595 /* continuation for OP_SGET */
   8596 
   8597     /*
   8598      * Continuation if the field has not yet been resolved.
   8599      *  r1: BBBB field ref
   8600      */
   8601 .LOP_SGET_resolve:
   8602     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8603     EXPORT_PC()                         @ resolve() could throw, so export now
   8604     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8605     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8606     cmp     r0, #0                      @ success?
   8607     bne     .LOP_SGET_finish          @ yes, finish
   8608     b       common_exceptionThrown      @ no, handle exception
   8609 
   8610 /* continuation for OP_SGET_WIDE */
   8611 
   8612     /*
   8613      * Continuation if the field has not yet been resolved.
   8614      *  r1: BBBB field ref
   8615      *
   8616      * Returns StaticField pointer in r0.
   8617      */
   8618 .LOP_SGET_WIDE_resolve:
   8619     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8620     EXPORT_PC()                         @ resolve() could throw, so export now
   8621     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8622     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8623     cmp     r0, #0                      @ success?
   8624     bne     .LOP_SGET_WIDE_finish          @ yes, finish
   8625     b       common_exceptionThrown      @ no, handle exception
   8626 
   8627 /* continuation for OP_SGET_OBJECT */
   8628 
   8629     /*
   8630      * Continuation if the field has not yet been resolved.
   8631      *  r1: BBBB field ref
   8632      */
   8633 .LOP_SGET_OBJECT_resolve:
   8634     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8635     EXPORT_PC()                         @ resolve() could throw, so export now
   8636     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8637     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8638     cmp     r0, #0                      @ success?
   8639     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
   8640     b       common_exceptionThrown      @ no, handle exception
   8641 
   8642 /* continuation for OP_SGET_BOOLEAN */
   8643 
   8644     /*
   8645      * Continuation if the field has not yet been resolved.
   8646      *  r1: BBBB field ref
   8647      */
   8648 .LOP_SGET_BOOLEAN_resolve:
   8649     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8650     EXPORT_PC()                         @ resolve() could throw, so export now
   8651     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8652     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8653     cmp     r0, #0                      @ success?
   8654     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
   8655     b       common_exceptionThrown      @ no, handle exception
   8656 
   8657 /* continuation for OP_SGET_BYTE */
   8658 
   8659     /*
   8660      * Continuation if the field has not yet been resolved.
   8661      *  r1: BBBB field ref
   8662      */
   8663 .LOP_SGET_BYTE_resolve:
   8664     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8665     EXPORT_PC()                         @ resolve() could throw, so export now
   8666     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8667     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8668     cmp     r0, #0                      @ success?
   8669     bne     .LOP_SGET_BYTE_finish          @ yes, finish
   8670     b       common_exceptionThrown      @ no, handle exception
   8671 
   8672 /* continuation for OP_SGET_CHAR */
   8673 
   8674     /*
   8675      * Continuation if the field has not yet been resolved.
   8676      *  r1: BBBB field ref
   8677      */
   8678 .LOP_SGET_CHAR_resolve:
   8679     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8680     EXPORT_PC()                         @ resolve() could throw, so export now
   8681     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8682     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8683     cmp     r0, #0                      @ success?
   8684     bne     .LOP_SGET_CHAR_finish          @ yes, finish
   8685     b       common_exceptionThrown      @ no, handle exception
   8686 
   8687 /* continuation for OP_SGET_SHORT */
   8688 
   8689     /*
   8690      * Continuation if the field has not yet been resolved.
   8691      *  r1: BBBB field ref
   8692      */
   8693 .LOP_SGET_SHORT_resolve:
   8694     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8695     EXPORT_PC()                         @ resolve() could throw, so export now
   8696     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8697     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8698     cmp     r0, #0                      @ success?
   8699     bne     .LOP_SGET_SHORT_finish          @ yes, finish
   8700     b       common_exceptionThrown      @ no, handle exception
   8701 
   8702 /* continuation for OP_SPUT */
   8703 
   8704     /*
   8705      * Continuation if the field has not yet been resolved.
   8706      *  r1: BBBB field ref
   8707      */
   8708 .LOP_SPUT_resolve:
   8709     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8710     EXPORT_PC()                         @ resolve() could throw, so export now
   8711     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8712     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8713     cmp     r0, #0                      @ success?
   8714     bne     .LOP_SPUT_finish          @ yes, finish
   8715     b       common_exceptionThrown      @ no, handle exception
   8716 
   8717 /* continuation for OP_SPUT_WIDE */
   8718 
   8719     /*
   8720      * Continuation if the field has not yet been resolved.
   8721      *  r1: BBBB field ref
   8722      *  r9: &fp[AA]
   8723      *
   8724      * Returns StaticField pointer in r2.
   8725      */
   8726 .LOP_SPUT_WIDE_resolve:
   8727     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8728     EXPORT_PC()                         @ resolve() could throw, so export now
   8729     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8730     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8731     cmp     r0, #0                      @ success?
   8732     mov     r2, r0                      @ copy to r2
   8733     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
   8734     b       common_exceptionThrown      @ no, handle exception
   8735 
   8736 /* continuation for OP_SPUT_OBJECT */
   8737 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
   8738     mov     r2, rINST, lsr #8           @ r2<- AA
   8739     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8740     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   8741     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8742     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
   8743     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8744     @ no-op                             @ releasing store
   8745     str     r1, [r0, #offStaticField_value]  @ field<- vAA
   8746     cmp     r1, #0                      @ stored a null object?
   8747     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
   8748     GOTO_OPCODE(ip)                     @ jump to next instruction
   8749 
   8750 /* continuation for OP_SPUT_BOOLEAN */
   8751 
   8752     /*
   8753      * Continuation if the field has not yet been resolved.
   8754      *  r1: BBBB field ref
   8755      */
   8756 .LOP_SPUT_BOOLEAN_resolve:
   8757     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8758     EXPORT_PC()                         @ resolve() could throw, so export now
   8759     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8760     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8761     cmp     r0, #0                      @ success?
   8762     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
   8763     b       common_exceptionThrown      @ no, handle exception
   8764 
   8765 /* continuation for OP_SPUT_BYTE */
   8766 
   8767     /*
   8768      * Continuation if the field has not yet been resolved.
   8769      *  r1: BBBB field ref
   8770      */
   8771 .LOP_SPUT_BYTE_resolve:
   8772     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8773     EXPORT_PC()                         @ resolve() could throw, so export now
   8774     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8775     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8776     cmp     r0, #0                      @ success?
   8777     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
   8778     b       common_exceptionThrown      @ no, handle exception
   8779 
   8780 /* continuation for OP_SPUT_CHAR */
   8781 
   8782     /*
   8783      * Continuation if the field has not yet been resolved.
   8784      *  r1: BBBB field ref
   8785      */
   8786 .LOP_SPUT_CHAR_resolve:
   8787     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8788     EXPORT_PC()                         @ resolve() could throw, so export now
   8789     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8790     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8791     cmp     r0, #0                      @ success?
   8792     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
   8793     b       common_exceptionThrown      @ no, handle exception
   8794 
   8795 /* continuation for OP_SPUT_SHORT */
   8796 
   8797     /*
   8798      * Continuation if the field has not yet been resolved.
   8799      *  r1: BBBB field ref
   8800      */
   8801 .LOP_SPUT_SHORT_resolve:
   8802     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8803     EXPORT_PC()                         @ resolve() could throw, so export now
   8804     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8805     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8806     cmp     r0, #0                      @ success?
   8807     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
   8808     b       common_exceptionThrown      @ no, handle exception
   8809 
   8810 /* continuation for OP_INVOKE_VIRTUAL */
   8811 
   8812     /*
   8813      * At this point:
   8814      *  r0 = resolved base method
   8815      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
   8816      */
   8817 .LOP_INVOKE_VIRTUAL_continue:
   8818     GET_VREG(r1, r10)                   @ r1<- "this" ptr
   8819     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8820     cmp     r1, #0                      @ is "this" null?
   8821     beq     common_errNullObject        @ null "this", throw exception
   8822     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
   8823     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
   8824     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8825     bl      common_invokeMethodNoRange @ continue on
   8826 
   8827 /* continuation for OP_INVOKE_SUPER */
   8828 
   8829     /*
   8830      * At this point:
   8831      *  r0 = resolved base method
   8832      *  r9 = method->clazz
   8833      */
   8834 .LOP_INVOKE_SUPER_continue:
   8835     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
   8836     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8837     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
   8838     EXPORT_PC()                         @ must export for invoke
   8839     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
   8840     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
   8841     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
   8842     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8843     bl      common_invokeMethodNoRange @ continue on
   8844 
   8845 .LOP_INVOKE_SUPER_resolve:
   8846     mov     r0, r9                      @ r0<- method->clazz
   8847     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   8848     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8849     cmp     r0, #0                      @ got null?
   8850     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
   8851     b       common_exceptionThrown      @ yes, handle exception
   8852 
   8853     /*
   8854      * Throw a NoSuchMethodError with the method name as the message.
   8855      *  r0 = resolved base method
   8856      */
   8857 .LOP_INVOKE_SUPER_nsm:
   8858     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
   8859     b       common_errNoSuchMethod
   8860 
   8861 /* continuation for OP_INVOKE_DIRECT */
   8862 
   8863     /*
   8864      * On entry:
   8865      *  r1 = reference (BBBB or CCCC)
   8866      *  r10 = "this" register
   8867      */
   8868 .LOP_INVOKE_DIRECT_resolve:
   8869     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8870     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8871     mov     r2, #METHOD_DIRECT          @ resolver method type
   8872     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8873     cmp     r0, #0                      @ got null?
   8874     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
   8875     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
   8876     b       common_exceptionThrown      @ yes, handle exception
   8877 
   8878 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
   8879 
   8880     /*
   8881      * At this point:
   8882      *  r0 = resolved base method
   8883      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
   8884      */
   8885 .LOP_INVOKE_VIRTUAL_RANGE_continue:
   8886     GET_VREG(r1, r10)                   @ r1<- "this" ptr
   8887     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8888     cmp     r1, #0                      @ is "this" null?
   8889     beq     common_errNullObject        @ null "this", throw exception
   8890     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
   8891     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
   8892     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8893     bl      common_invokeMethodRange @ continue on
   8894 
   8895 /* continuation for OP_INVOKE_SUPER_RANGE */
   8896 
   8897     /*
   8898      * At this point:
   8899      *  r0 = resolved base method
   8900      *  r9 = method->clazz
   8901      */
   8902 .LOP_INVOKE_SUPER_RANGE_continue:
   8903     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
   8904     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   8905     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
   8906     EXPORT_PC()                         @ must export for invoke
   8907     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
   8908     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
   8909     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
   8910     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
   8911     bl      common_invokeMethodRange @ continue on
   8912 
   8913 .LOP_INVOKE_SUPER_RANGE_resolve:
   8914     mov     r0, r9                      @ r0<- method->clazz
   8915     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   8916     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8917     cmp     r0, #0                      @ got null?
   8918     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
   8919     b       common_exceptionThrown      @ yes, handle exception
   8920 
   8921     /*
   8922      * Throw a NoSuchMethodError with the method name as the message.
   8923      *  r0 = resolved base method
   8924      */
   8925 .LOP_INVOKE_SUPER_RANGE_nsm:
   8926     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
   8927     b       common_errNoSuchMethod
   8928 
   8929 /* continuation for OP_INVOKE_DIRECT_RANGE */
   8930 
   8931     /*
   8932      * On entry:
   8933      *  r1 = reference (BBBB or CCCC)
   8934      *  r10 = "this" register
   8935      */
   8936 .LOP_INVOKE_DIRECT_RANGE_resolve:
   8937     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8938     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8939     mov     r2, #METHOD_DIRECT          @ resolver method type
   8940     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   8941     cmp     r0, #0                      @ got null?
   8942     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
   8943     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
   8944     b       common_exceptionThrown      @ yes, handle exception
   8945 
   8946 /* continuation for OP_FLOAT_TO_LONG */
   8947 /*
   8948  * Convert the float in r0 to a long in r0/r1.
   8949  *
   8950  * We have to clip values to long min/max per the specification.  The
   8951  * expected common case is a "reasonable" value that converts directly
   8952  * to modest integer.  The EABI convert function isn't doing this for us.
   8953  */
   8954 f2l_doconv:
   8955     stmfd   sp!, {r4, lr}
   8956     mov     r1, #0x5f000000             @ (float)maxlong
   8957     mov     r4, r0
   8958     bl      __aeabi_fcmpge              @ is arg >= maxlong?
   8959     cmp     r0, #0                      @ nonzero == yes
   8960     mvnne   r0, #0                      @ return maxlong (7fffffff)
   8961     mvnne   r1, #0x80000000
   8962     ldmnefd sp!, {r4, pc}
   8963 
   8964     mov     r0, r4                      @ recover arg
   8965     mov     r1, #0xdf000000             @ (float)minlong
   8966     bl      __aeabi_fcmple              @ is arg <= minlong?
   8967     cmp     r0, #0                      @ nonzero == yes
   8968     movne   r0, #0                      @ return minlong (80000000)
   8969     movne   r1, #0x80000000
   8970     ldmnefd sp!, {r4, pc}
   8971 
   8972     mov     r0, r4                      @ recover arg
   8973     mov     r1, r4
   8974     bl      __aeabi_fcmpeq              @ is arg == self?
   8975     cmp     r0, #0                      @ zero == no
   8976     moveq   r1, #0                      @ return zero for NaN
   8977     ldmeqfd sp!, {r4, pc}
   8978 
   8979     mov     r0, r4                      @ recover arg
   8980     bl      __aeabi_f2lz                @ convert float to long
   8981     ldmfd   sp!, {r4, pc}
   8982 
   8983 /* continuation for OP_DOUBLE_TO_LONG */
   8984 /*
   8985  * Convert the double in r0/r1 to a long in r0/r1.
   8986  *
   8987  * We have to clip values to long min/max per the specification.  The
   8988  * expected common case is a "reasonable" value that converts directly
   8989  * to modest integer.  The EABI convert function isn't doing this for us.
   8990  */
   8991 d2l_doconv:
   8992     stmfd   sp!, {r4, r5, lr}           @ save regs
   8993     mov     r3, #0x43000000             @ maxlong, as a double (high word)
   8994     add     r3, #0x00e00000             @  0x43e00000
   8995     mov     r2, #0                      @ maxlong, as a double (low word)
   8996     sub     sp, sp, #4                  @ align for EABI
   8997     mov     r4, r0                      @ save a copy of r0
   8998     mov     r5, r1                      @  and r1
   8999     bl      __aeabi_dcmpge              @ is arg >= maxlong?
   9000     cmp     r0, #0                      @ nonzero == yes
   9001     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
   9002     mvnne   r1, #0x80000000
   9003     bne     1f
   9004 
   9005     mov     r0, r4                      @ recover arg
   9006     mov     r1, r5
   9007     mov     r3, #0xc3000000             @ minlong, as a double (high word)
   9008     add     r3, #0x00e00000             @  0xc3e00000
   9009     mov     r2, #0                      @ minlong, as a double (low word)
   9010     bl      __aeabi_dcmple              @ is arg <= minlong?
   9011     cmp     r0, #0                      @ nonzero == yes
   9012     movne   r0, #0                      @ return minlong (8000000000000000)
   9013     movne   r1, #0x80000000
   9014     bne     1f
   9015 
   9016     mov     r0, r4                      @ recover arg
   9017     mov     r1, r5
   9018     mov     r2, r4                      @ compare against self
   9019     mov     r3, r5
   9020     bl      __aeabi_dcmpeq              @ is arg == self?
   9021     cmp     r0, #0                      @ zero == no
   9022     moveq   r1, #0                      @ return zero for NaN
   9023     beq     1f
   9024 
   9025     mov     r0, r4                      @ recover arg
   9026     mov     r1, r5
   9027     bl      __aeabi_d2lz                @ convert double to long
   9028 
   9029 1:
   9030     add     sp, sp, #4
   9031     ldmfd   sp!, {r4, r5, pc}
   9032 
   9033 /* continuation for OP_MUL_LONG */
   9034 
   9035 .LOP_MUL_LONG_finish:
   9036     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9037     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
   9038     GOTO_OPCODE(ip)                     @ jump to next instruction
   9039 
   9040 /* continuation for OP_SHL_LONG */
   9041 
   9042 .LOP_SHL_LONG_finish:
   9043     mov     r0, r0, asl r2              @  r0<- r0 << r2
   9044     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9045     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9046     GOTO_OPCODE(ip)                     @ jump to next instruction
   9047 
   9048 /* continuation for OP_SHR_LONG */
   9049 
   9050 .LOP_SHR_LONG_finish:
   9051     mov     r1, r1, asr r2              @  r1<- r1 >> r2
   9052     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9053     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9054     GOTO_OPCODE(ip)                     @ jump to next instruction
   9055 
   9056 /* continuation for OP_USHR_LONG */
   9057 
   9058 .LOP_USHR_LONG_finish:
   9059     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
   9060     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9061     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9062     GOTO_OPCODE(ip)                     @ jump to next instruction
   9063 
   9064 /* continuation for OP_SHL_LONG_2ADDR */
   9065 
   9066 .LOP_SHL_LONG_2ADDR_finish:
   9067     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9068     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9069     GOTO_OPCODE(ip)                     @ jump to next instruction
   9070 
   9071 /* continuation for OP_SHR_LONG_2ADDR */
   9072 
   9073 .LOP_SHR_LONG_2ADDR_finish:
   9074     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9075     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9076     GOTO_OPCODE(ip)                     @ jump to next instruction
   9077 
   9078 /* continuation for OP_USHR_LONG_2ADDR */
   9079 
   9080 .LOP_USHR_LONG_2ADDR_finish:
   9081     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9082     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9083     GOTO_OPCODE(ip)                     @ jump to next instruction
   9084 
   9085 /* continuation for OP_IGET_VOLATILE */
   9086 
   9087     /*
   9088      * Currently:
   9089      *  r0 holds resolved field
   9090      *  r9 holds object
   9091      */
   9092 .LOP_IGET_VOLATILE_finish:
   9093     @bl      common_squeak0
   9094     cmp     r9, #0                      @ check object for null
   9095     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9096     beq     common_errNullObject        @ object was null
   9097     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   9098     SMP_DMB                            @ acquiring load
   9099     mov     r2, rINST, lsr #8           @ r2<- A+
   9100     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9101     and     r2, r2, #15                 @ r2<- A
   9102     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9103     SET_VREG(r0, r2)                    @ fp[A]<- r0
   9104     GOTO_OPCODE(ip)                     @ jump to next instruction
   9105 
   9106 /* continuation for OP_IPUT_VOLATILE */
   9107 
   9108     /*
   9109      * Currently:
   9110      *  r0 holds resolved field
   9111      *  r9 holds object
   9112      */
   9113 .LOP_IPUT_VOLATILE_finish:
   9114     @bl      common_squeak0
   9115     mov     r1, rINST, lsr #8           @ r1<- A+
   9116     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9117     and     r1, r1, #15                 @ r1<- A
   9118     cmp     r9, #0                      @ check object for null
   9119     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9120     beq     common_errNullObject        @ object was null
   9121     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9122     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9123     SMP_DMB                            @ releasing store
   9124     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   9125     GOTO_OPCODE(ip)                     @ jump to next instruction
   9126 
   9127 /* continuation for OP_SGET_VOLATILE */
   9128 
   9129     /*
   9130      * Continuation if the field has not yet been resolved.
   9131      *  r1: BBBB field ref
   9132      */
   9133 .LOP_SGET_VOLATILE_resolve:
   9134     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9135     EXPORT_PC()                         @ resolve() could throw, so export now
   9136     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9137     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9138     cmp     r0, #0                      @ success?
   9139     bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
   9140     b       common_exceptionThrown      @ no, handle exception
   9141 
   9142 /* continuation for OP_SPUT_VOLATILE */
   9143 
   9144     /*
   9145      * Continuation if the field has not yet been resolved.
   9146      *  r1: BBBB field ref
   9147      */
   9148 .LOP_SPUT_VOLATILE_resolve:
   9149     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9150     EXPORT_PC()                         @ resolve() could throw, so export now
   9151     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9152     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9153     cmp     r0, #0                      @ success?
   9154     bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
   9155     b       common_exceptionThrown      @ no, handle exception
   9156 
   9157 /* continuation for OP_IGET_OBJECT_VOLATILE */
   9158 
   9159     /*
   9160      * Currently:
   9161      *  r0 holds resolved field
   9162      *  r9 holds object
   9163      */
   9164 .LOP_IGET_OBJECT_VOLATILE_finish:
   9165     @bl      common_squeak0
   9166     cmp     r9, #0                      @ check object for null
   9167     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9168     beq     common_errNullObject        @ object was null
   9169     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   9170     SMP_DMB                            @ acquiring load
   9171     mov     r2, rINST, lsr #8           @ r2<- A+
   9172     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9173     and     r2, r2, #15                 @ r2<- A
   9174     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9175     SET_VREG(r0, r2)                    @ fp[A]<- r0
   9176     GOTO_OPCODE(ip)                     @ jump to next instruction
   9177 
   9178 /* continuation for OP_IGET_WIDE_VOLATILE */
   9179 
   9180     /*
   9181      * Currently:
   9182      *  r0 holds resolved field
   9183      *  r9 holds object
   9184      */
   9185 .LOP_IGET_WIDE_VOLATILE_finish:
   9186     cmp     r9, #0                      @ check object for null
   9187     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9188     beq     common_errNullObject        @ object was null
   9189     .if     1
   9190     add     r0, r9, r3                  @ r0<- address of field
   9191     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   9192     .else
   9193     ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
   9194     .endif
   9195     mov     r2, rINST, lsr #8           @ r2<- A+
   9196     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9197     and     r2, r2, #15                 @ r2<- A
   9198     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   9199     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9200     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   9201     GOTO_OPCODE(ip)                     @ jump to next instruction
   9202 
   9203 /* continuation for OP_IPUT_WIDE_VOLATILE */
   9204 
   9205     /*
   9206      * Currently:
   9207      *  r0 holds resolved field
   9208      *  r9 holds object
   9209      */
   9210 .LOP_IPUT_WIDE_VOLATILE_finish:
   9211     mov     r2, rINST, lsr #8           @ r2<- A+
   9212     cmp     r9, #0                      @ check object for null
   9213     and     r2, r2, #15                 @ r2<- A
   9214     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9215     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
   9216     beq     common_errNullObject        @ object was null
   9217     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9218     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
   9219     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   9220     .if     1
   9221     add     r2, r9, r3                  @ r2<- target address
   9222     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   9223     .else
   9224     strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
   9225     .endif
   9226     GOTO_OPCODE(r10)                    @ jump to next instruction
   9227 
   9228 /* continuation for OP_SGET_WIDE_VOLATILE */
   9229 
   9230     /*
   9231      * Continuation if the field has not yet been resolved.
   9232      *  r1: BBBB field ref
   9233      *
   9234      * Returns StaticField pointer in r0.
   9235      */
   9236 .LOP_SGET_WIDE_VOLATILE_resolve:
   9237     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9238     EXPORT_PC()                         @ resolve() could throw, so export now
   9239     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9240     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9241     cmp     r0, #0                      @ success?
   9242     bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
   9243     b       common_exceptionThrown      @ no, handle exception
   9244 
   9245 /* continuation for OP_SPUT_WIDE_VOLATILE */
   9246 
   9247     /*
   9248      * Continuation if the field has not yet been resolved.
   9249      *  r1: BBBB field ref
   9250      *  r9: &fp[AA]
   9251      *
   9252      * Returns StaticField pointer in r2.
   9253      */
   9254 .LOP_SPUT_WIDE_VOLATILE_resolve:
   9255     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9256     EXPORT_PC()                         @ resolve() could throw, so export now
   9257     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9258     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9259     cmp     r0, #0                      @ success?
   9260     mov     r2, r0                      @ copy to r2
   9261     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
   9262     b       common_exceptionThrown      @ no, handle exception
   9263 
   9264 /* continuation for OP_EXECUTE_INLINE */
   9265 
   9266     /*
   9267      * Extract args, call function.
   9268      *  r0 = #of args (0-4)
   9269      *  r10 = call index
   9270      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
   9271      *
   9272      * Other ideas:
   9273      * - Use a jump table from the main piece to jump directly into the
   9274      *   AND/LDR pairs.  Costs a data load, saves a branch.
   9275      * - Have five separate pieces that do the loading, so we can work the
   9276      *   interleave a little better.  Increases code size.
   9277      */
   9278 .LOP_EXECUTE_INLINE_continue:
   9279     rsb     r0, r0, #4                  @ r0<- 4-r0
   9280     FETCH(r9, 2)                        @ r9<- FEDC
   9281     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
   9282     bl      common_abort                @ (skipped due to ARM prefetch)
   9283 4:  and     ip, r9, #0xf000             @ isolate F
   9284     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
   9285 3:  and     ip, r9, #0x0f00             @ isolate E
   9286     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
   9287 2:  and     ip, r9, #0x00f0             @ isolate D
   9288     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
   9289 1:  and     ip, r9, #0x000f             @ isolate C
   9290     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
   9291 0:
   9292     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
   9293     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
   9294     @ (not reached)
   9295 
   9296 .LOP_EXECUTE_INLINE_table:
   9297     .word   gDvmInlineOpsTable
   9298 
   9299 /* continuation for OP_EXECUTE_INLINE_RANGE */
   9300 
   9301     /*
   9302      * Extract args, call function.
   9303      *  r0 = #of args (0-4)
   9304      *  r10 = call index
   9305      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
   9306      */
   9307 .LOP_EXECUTE_INLINE_RANGE_continue:
   9308     rsb     r0, r0, #4                  @ r0<- 4-r0
   9309     FETCH(r9, 2)                        @ r9<- CCCC
   9310     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
   9311     bl      common_abort                @ (skipped due to ARM prefetch)
   9312 4:  add     ip, r9, #3                  @ base+3
   9313     GET_VREG(r3, ip)                    @ r3<- vBase[3]
   9314 3:  add     ip, r9, #2                  @ base+2
   9315     GET_VREG(r2, ip)                    @ r2<- vBase[2]
   9316 2:  add     ip, r9, #1                  @ base+1
   9317     GET_VREG(r1, ip)                    @ r1<- vBase[1]
   9318 1:  add     ip, r9, #0                  @ (nop)
   9319     GET_VREG(r0, ip)                    @ r0<- vBase[0]
   9320 0:
   9321     ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
   9322     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
   9323     @ (not reached)
   9324 
   9325 .LOP_EXECUTE_INLINE_RANGE_table:
   9326     .word   gDvmInlineOpsTable
   9327 
   9328 /* continuation for OP_IPUT_OBJECT_VOLATILE */
   9329 
   9330     /*
   9331      * Currently:
   9332      *  r0 holds resolved field
   9333      *  r9 holds object
   9334      */
   9335 .LOP_IPUT_OBJECT_VOLATILE_finish:
   9336     @bl      common_squeak0
   9337     mov     r1, rINST, lsr #8           @ r1<- A+
   9338     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9339     and     r1, r1, #15                 @ r1<- A
   9340     cmp     r9, #0                      @ check object for null
   9341     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9342     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9343     beq     common_errNullObject        @ object was null
   9344     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9345     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9346     SMP_DMB                            @ releasing store
   9347     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
   9348     cmp     r0, #0                      @ stored a null reference?
   9349     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
   9350     GOTO_OPCODE(ip)                     @ jump to next instruction
   9351 
   9352 /* continuation for OP_SGET_OBJECT_VOLATILE */
   9353 
   9354     /*
   9355      * Continuation if the field has not yet been resolved.
   9356      *  r1: BBBB field ref
   9357      */
   9358 .LOP_SGET_OBJECT_VOLATILE_resolve:
   9359     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9360     EXPORT_PC()                         @ resolve() could throw, so export now
   9361     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9362     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9363     cmp     r0, #0                      @ success?
   9364     bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
   9365     b       common_exceptionThrown      @ no, handle exception
   9366 
   9367 /* continuation for OP_SPUT_OBJECT_VOLATILE */
   9368 .LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
   9369     mov     r2, rINST, lsr #8           @ r2<- AA
   9370     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9371     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   9372     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9373     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
   9374     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9375     SMP_DMB                            @ releasing store
   9376     str     r1, [r0, #offStaticField_value]  @ field<- vAA
   9377     cmp     r1, #0                      @ stored a null object?
   9378     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
   9379     GOTO_OPCODE(ip)                     @ jump to next instruction
   9380 
   9381     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
   9382     .global dvmAsmSisterEnd
   9383 dvmAsmSisterEnd:
   9384 
   9385 /* File: armv5te/footer.S */
   9386 
   9387 /*
   9388  * ===========================================================================
   9389  *  Common subroutines and data
   9390  * ===========================================================================
   9391  */
   9392 
   9393 
   9394 
   9395     .text
   9396     .align  2
   9397 
   9398 #if defined(WITH_JIT)
   9399 #if defined(WITH_SELF_VERIFICATION)
   9400     .global dvmJitToInterpPunt
   9401 dvmJitToInterpPunt:
   9402     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9403     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
   9404     mov    r3, #0
   9405     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9406     b      jitSVShadowRunEnd            @ doesn't return
   9407 
   9408     .global dvmJitToInterpSingleStep
   9409 dvmJitToInterpSingleStep:
   9410     str    lr,[rGLUE,#offGlue_jitResumeNPC]
   9411     str    r1,[rGLUE,#offGlue_jitResumeDPC]
   9412     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
   9413     b      jitSVShadowRunEnd            @ doesn't return
   9414 
   9415     .global dvmJitToInterpNoChainNoProfile
   9416 dvmJitToInterpNoChainNoProfile:
   9417     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9418     mov    r0,rPC                       @ pass our target PC
   9419     mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
   9420     mov    r3, #0                       @ 0 means !inJitCodeCache
   9421     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
   9422     b      jitSVShadowRunEnd            @ doesn't return
   9423 
   9424     .global dvmJitToInterpTraceSelectNoChain
   9425 dvmJitToInterpTraceSelectNoChain:
   9426     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9427     mov    r0,rPC                       @ pass our target PC
   9428     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
   9429     mov    r3, #0                       @ 0 means !inJitCodeCache
   9430     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9431     b      jitSVShadowRunEnd            @ doesn't return
   9432 
   9433     .global dvmJitToInterpTraceSelect
   9434 dvmJitToInterpTraceSelect:
   9435     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9436     ldr    r0,[lr, #-1]                 @ pass our target PC
   9437     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
   9438     mov    r3, #0                       @ 0 means !inJitCodeCache
   9439     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9440     b      jitSVShadowRunEnd            @ doesn't return
   9441 
   9442     .global dvmJitToInterpBackwardBranch
   9443 dvmJitToInterpBackwardBranch:
   9444     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9445     ldr    r0,[lr, #-1]                 @ pass our target PC
   9446     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
   9447     mov    r3, #0                       @ 0 means !inJitCodeCache
   9448     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9449     b      jitSVShadowRunEnd            @ doesn't return
   9450 
   9451     .global dvmJitToInterpNormal
   9452 dvmJitToInterpNormal:
   9453     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9454     ldr    r0,[lr, #-1]                 @ pass our target PC
   9455     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
   9456     mov    r3, #0                       @ 0 means !inJitCodeCache
   9457     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9458     b      jitSVShadowRunEnd            @ doesn't return
   9459 
   9460     .global dvmJitToInterpNoChain
   9461 dvmJitToInterpNoChain:
   9462     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9463     mov    r0,rPC                       @ pass our target PC
   9464     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
   9465     mov    r3, #0                       @ 0 means !inJitCodeCache
   9466     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9467     b      jitSVShadowRunEnd            @ doesn't return
   9468 #else
   9469 /*
   9470  * Return from the translation cache to the interpreter when the compiler is
   9471  * having issues translating/executing a Dalvik instruction. We have to skip
   9472  * the code cache lookup otherwise it is possible to indefinitely bouce
   9473  * between the interpreter and the code cache if the instruction that fails
   9474  * to be compiled happens to be at a trace start.
   9475  */
   9476     .global dvmJitToInterpPunt
   9477 dvmJitToInterpPunt:
   9478     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9479     mov    rPC, r0
   9480 #if defined(WITH_JIT_TUNING)
   9481     mov    r0,lr
   9482     bl     dvmBumpPunt;
   9483 #endif
   9484     EXPORT_PC()
   9485     mov    r0, #0
   9486     str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9487     adrl   rIBASE, dvmAsmInstructionStart
   9488     FETCH_INST()
   9489     GET_INST_OPCODE(ip)
   9490     GOTO_OPCODE(ip)
   9491 
   9492 /*
   9493  * Return to the interpreter to handle a single instruction.
   9494  * On entry:
   9495  *    r0 <= PC
   9496  *    r1 <= PC of resume instruction
   9497  *    lr <= resume point in translation
   9498  */
   9499     .global dvmJitToInterpSingleStep
   9500 dvmJitToInterpSingleStep:
   9501     str    lr,[rGLUE,#offGlue_jitResumeNPC]
   9502     str    r1,[rGLUE,#offGlue_jitResumeDPC]
   9503     mov    r1,#kInterpEntryInstr
   9504     @ enum is 4 byte in aapcs-EABI
   9505     str    r1, [rGLUE, #offGlue_entryPoint]
   9506     mov    rPC,r0
   9507     EXPORT_PC()
   9508 
   9509     adrl   rIBASE, dvmAsmInstructionStart
   9510     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
   9511     str    r2,[rGLUE,#offGlue_jitState]
   9512     mov    r1,#1                  @ set changeInterp to bail to debug interp
   9513     b      common_gotoBail
   9514 
   9515 /*
   9516  * Return from the translation cache and immediately request
   9517  * a translation for the exit target.  Commonly used for callees.
   9518  */
   9519     .global dvmJitToInterpTraceSelectNoChain
   9520 dvmJitToInterpTraceSelectNoChain:
   9521 #if defined(WITH_JIT_TUNING)
   9522     bl     dvmBumpNoChain
   9523 #endif
   9524     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9525     mov    r0,rPC
   9526     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9527     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9528     mov    r1, rPC                  @ arg1 of translation may need this
   9529     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9530     cmp    r0,#0                    @ !0 means translation exists
   9531     bxne   r0                       @ continue native execution if so
   9532     b      2f                       @ branch over to use the interpreter
   9533 
   9534 /*
   9535  * Return from the translation cache and immediately request
   9536  * a translation for the exit target.  Commonly used following
   9537  * invokes.
   9538  */
   9539     .global dvmJitToInterpTraceSelect
   9540 dvmJitToInterpTraceSelect:
   9541     ldr    rPC,[lr, #-1]           @ get our target PC
   9542     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9543     add    rINST,lr,#-5            @ save start of chain branch
   9544     add    rINST, #-4              @  .. which is 9 bytes back
   9545     mov    r0,rPC
   9546     bl     dvmJitGetCodeAddr       @ Is there a translation?
   9547     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9548     cmp    r0,#0
   9549     beq    2f
   9550     mov    r1,rINST
   9551     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
   9552     mov    r1, rPC                  @ arg1 of translation may need this
   9553     mov    lr, #0                   @ in case target is HANDLER_INTERPRET
   9554     cmp    r0,#0                    @ successful chain?
   9555     bxne   r0                       @ continue native execution
   9556     b      toInterpreter            @ didn't chain - resume with interpreter
   9557 
   9558 /* No translation, so request one if profiling isn't disabled*/
   9559 2:
   9560     adrl   rIBASE, dvmAsmInstructionStart
   9561     GET_JIT_PROF_TABLE(r0)
   9562     FETCH_INST()
   9563     cmp    r0, #0
   9564     movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
   9565     bne    common_selectTrace
   9566     GET_INST_OPCODE(ip)
   9567     GOTO_OPCODE(ip)
   9568 
   9569 /*
   9570  * Return from the translation cache to the interpreter.
   9571  * The return was done with a BLX from thumb mode, and
   9572  * the following 32-bit word contains the target rPC value.
   9573  * Note that lr (r14) will have its low-order bit set to denote
   9574  * its thumb-mode origin.
   9575  *
   9576  * We'll need to stash our lr origin away, recover the new
   9577  * target and then check to see if there is a translation available
   9578  * for our new target.  If so, we do a translation chain and
   9579  * go back to native execution.  Otherwise, it's back to the
   9580  * interpreter (after treating this entry as a potential
   9581  * trace start).
   9582  */
   9583     .global dvmJitToInterpNormal
   9584 dvmJitToInterpNormal:
   9585     ldr    rPC,[lr, #-1]           @ get our target PC
   9586     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9587     add    rINST,lr,#-5            @ save start of chain branch
   9588     add    rINST,#-4               @ .. which is 9 bytes back
   9589 #if defined(WITH_JIT_TUNING)
   9590     bl     dvmBumpNormal
   9591 #endif
   9592     mov    r0,rPC
   9593     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9594     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9595     cmp    r0,#0
   9596     beq    toInterpreter            @ go if not, otherwise do chain
   9597     mov    r1,rINST
   9598     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
   9599     mov    r1, rPC                  @ arg1 of translation may need this
   9600     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9601     cmp    r0,#0                    @ successful chain?
   9602     bxne   r0                       @ continue native execution
   9603     b      toInterpreter            @ didn't chain - resume with interpreter
   9604 
   9605 /*
   9606  * Return from the translation cache to the interpreter to do method invocation.
   9607  * Check if translation exists for the callee, but don't chain to it.
   9608  */
   9609     .global dvmJitToInterpNoChainNoProfile
   9610 dvmJitToInterpNoChainNoProfile:
   9611 #if defined(WITH_JIT_TUNING)
   9612     bl     dvmBumpNoChain
   9613 #endif
   9614     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9615     mov    r0,rPC
   9616     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9617     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9618     mov    r1, rPC                  @ arg1 of translation may need this
   9619     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9620     cmp    r0,#0
   9621     bxne   r0                       @ continue native execution if so
   9622     EXPORT_PC()
   9623     adrl   rIBASE, dvmAsmInstructionStart
   9624     FETCH_INST()
   9625     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9626     GOTO_OPCODE(ip)                     @ jump to next instruction
   9627 
   9628 /*
   9629  * Return from the translation cache to the interpreter to do method invocation.
   9630  * Check if translation exists for the callee, but don't chain to it.
   9631  */
   9632     .global dvmJitToInterpNoChain
   9633 dvmJitToInterpNoChain:
   9634 #if defined(WITH_JIT_TUNING)
   9635     bl     dvmBumpNoChain
   9636 #endif
   9637     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9638     mov    r0,rPC
   9639     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9640     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9641     mov    r1, rPC                  @ arg1 of translation may need this
   9642     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9643     cmp    r0,#0
   9644     bxne   r0                       @ continue native execution if so
   9645 #endif
   9646 
   9647 /*
   9648  * No translation, restore interpreter regs and start interpreting.
   9649  * rGLUE & rFP were preserved in the translated code, and rPC has
   9650  * already been restored by the time we get here.  We'll need to set
   9651  * up rIBASE & rINST, and load the address of the JitTable into r0.
   9652  */
   9653 toInterpreter:
   9654     EXPORT_PC()
   9655     adrl   rIBASE, dvmAsmInstructionStart
   9656     FETCH_INST()
   9657     GET_JIT_PROF_TABLE(r0)
   9658     @ NOTE: intended fallthrough
   9659 
   9660 /*
   9661  * Common code to update potential trace start counter, and initiate
   9662  * a trace-build if appropriate.  On entry, rPC should point to the
   9663  * next instruction to execute, and rINST should be already loaded with
   9664  * the next opcode word, and r0 holds a pointer to the jit profile
   9665  * table (pJitProfTable).
   9666  */
   9667 common_testUpdateProfile:
   9668     cmp     r0,#0
   9669     GET_INST_OPCODE(ip)
   9670     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
   9671 
   9672 common_updateProfile:
   9673     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
   9674     lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
   9675     ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
   9676     GET_INST_OPCODE(ip)
   9677     subs    r1,r1,#1           @ decrement counter
   9678     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
   9679     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
   9680 
   9681 /*
   9682  * Here, we switch to the debug interpreter to request
   9683  * trace selection.  First, though, check to see if there
   9684  * is already a native translation in place (and, if so,
   9685  * jump to it now).
   9686  */
   9687     GET_JIT_THRESHOLD(r1)
   9688     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
   9689     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
   9690     EXPORT_PC()
   9691     mov     r0,rPC
   9692     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
   9693     str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9694     mov     r1, rPC                     @ arg1 of translation may need this
   9695     mov     lr, #0                      @  in case target is HANDLER_INTERPRET
   9696     cmp     r0,#0
   9697 #if !defined(WITH_SELF_VERIFICATION)
   9698     bxne    r0                          @ jump to the translation
   9699     mov     r2,#kJitTSelectRequest      @ ask for trace selection
   9700     @ fall-through to common_selectTrace
   9701 #else
   9702     moveq   r2,#kJitTSelectRequest      @ ask for trace selection
   9703     beq     common_selectTrace
   9704     /*
   9705      * At this point, we have a target translation.  However, if
   9706      * that translation is actually the interpret-only pseudo-translation
   9707      * we want to treat it the same as no translation.
   9708      */
   9709     mov     r10, r0                     @ save target
   9710     bl      dvmCompilerGetInterpretTemplate
   9711     cmp     r0, r10                     @ special case?
   9712     bne     jitSVShadowRunStart         @ set up self verification shadow space
   9713     @ Need to clear the inJitCodeCache flag
   9714     ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
   9715     mov    r3, #0                       @ 0 means not in the JIT code cache
   9716     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
   9717     GET_INST_OPCODE(ip)
   9718     GOTO_OPCODE(ip)
   9719     /* no return */
   9720 #endif
   9721 
   9722 /*
   9723  * On entry:
   9724  *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
   9725  */
   9726 common_selectTrace:
   9727     str     r2,[rGLUE,#offGlue_jitState]
   9728     mov     r2,#kInterpEntryInstr       @ normal entry reason
   9729     str     r2,[rGLUE,#offGlue_entryPoint]
   9730     mov     r1,#1                       @ set changeInterp
   9731     b       common_gotoBail
   9732 
   9733 #if defined(WITH_SELF_VERIFICATION)
   9734 /*
   9735  * Save PC and registers to shadow memory for self verification mode
   9736  * before jumping to native translation.
   9737  * On entry:
   9738  *    rPC, rFP, rGLUE: the values that they should contain
   9739  *    r10: the address of the target translation.
   9740  */
   9741 jitSVShadowRunStart:
   9742     mov     r0,rPC                      @ r0<- program counter
   9743     mov     r1,rFP                      @ r1<- frame pointer
   9744     mov     r2,rGLUE                    @ r2<- InterpState pointer
   9745     mov     r3,r10                      @ r3<- target translation
   9746     bl      dvmSelfVerificationSaveState @ save registers to shadow space
   9747     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
   9748     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
   9749     bx      r10                         @ jump to the translation
   9750 
   9751 /*
   9752  * Restore PC, registers, and interpState to original values
   9753  * before jumping back to the interpreter.
   9754  */
   9755 jitSVShadowRunEnd:
   9756     mov    r1,rFP                        @ pass ending fp
   9757     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
   9758     ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
   9759     ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
   9760     ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
   9761     ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
   9762     cmp    r1,#0                         @ check for punt condition
   9763     beq    1f
   9764     mov    r2,#kJitSelfVerification      @ ask for self verification
   9765     str    r2,[rGLUE,#offGlue_jitState]
   9766     mov    r2,#kInterpEntryInstr         @ normal entry reason
   9767     str    r2,[rGLUE,#offGlue_entryPoint]
   9768     mov    r1,#1                         @ set changeInterp
   9769     b      common_gotoBail
   9770 
   9771 1:                                       @ exit to interpreter without check
   9772     EXPORT_PC()
   9773     adrl   rIBASE, dvmAsmInstructionStart
   9774     FETCH_INST()
   9775     GET_INST_OPCODE(ip)
   9776     GOTO_OPCODE(ip)
   9777 #endif
   9778 
   9779 #endif
   9780 
   9781 /*
   9782  * Common code when a backward branch is taken.
   9783  *
   9784  * TODO: we could avoid a branch by just setting r0 and falling through
   9785  * into the common_periodicChecks code, and having a test on r0 at the
   9786  * end determine if we should return to the caller or update & branch to
   9787  * the next instr.
   9788  *
   9789  * On entry:
   9790  *  r9 is PC adjustment *in bytes*
   9791  */
   9792 common_backwardBranch:
   9793     mov     r0, #kInterpEntryInstr
   9794     bl      common_periodicChecks
   9795 #if defined(WITH_JIT)
   9796     GET_JIT_PROF_TABLE(r0)
   9797     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   9798     cmp     r0,#0
   9799     bne     common_updateProfile
   9800     GET_INST_OPCODE(ip)
   9801     GOTO_OPCODE(ip)
   9802 #else
   9803     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   9804     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9805     GOTO_OPCODE(ip)                     @ jump to next instruction
   9806 #endif
   9807 
   9808 
   9809 /*
   9810  * Need to see if the thread needs to be suspended or debugger/profiler
   9811  * activity has begun.  If so, we suspend the thread or side-exit to
   9812  * the debug interpreter as appropriate.
   9813  *
   9814  * The common case is no activity on any of these, so we want to figure
   9815  * that out quickly.  If something is up, we can then sort out what.
   9816  *
   9817  * We want to be fast if the VM was built without debugger or profiler
   9818  * support, but we also need to recognize that the system is usually
   9819  * shipped with both of these enabled.
   9820  *
   9821  * TODO: reduce this so we're just checking a single location.
   9822  *
   9823  * On entry:
   9824  *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
   9825  *  r9 is trampoline PC adjustment *in bytes*
   9826  */
   9827 common_periodicChecks:
   9828     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
   9829 
   9830     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
   9831     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
   9832 
   9833     ldr     ip, [r3]                    @ ip<- suspendCount (int)
   9834 
   9835     cmp     r1, #0                      @ debugger enabled?
   9836     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
   9837     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
   9838     orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
   9839     orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
   9840 
   9841     bxeq    lr                          @ all zero, return
   9842 
   9843     /*
   9844      * One or more interesting events have happened.  Figure out what.
   9845      *
   9846      * If debugging or profiling are compiled in, we need to disambiguate.
   9847      *
   9848      * r0 still holds the reentry type.
   9849      */
   9850     ldr     ip, [r3]                    @ ip<- suspendCount (int)
   9851     cmp     ip, #0                      @ want suspend?
   9852     beq     1f                          @ no, must be debugger/profiler
   9853 
   9854     stmfd   sp!, {r0, lr}               @ preserve r0 and lr
   9855 #if defined(WITH_JIT)
   9856     /*
   9857      * Refresh the Jit's cached copy of profile table pointer.  This pointer
   9858      * doubles as the Jit's on/off switch.
   9859      */
   9860     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
   9861     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   9862     ldr     r3, [r3] @ r3 <- pJitProfTable
   9863     EXPORT_PC()                         @ need for precise GC
   9864     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
   9865 #else
   9866     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   9867     EXPORT_PC()                         @ need for precise GC
   9868 #endif
   9869     bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
   9870     ldmfd   sp!, {r0, lr}               @ restore r0 and lr
   9871 
   9872     /*
   9873      * Reload the debugger/profiler enable flags.  We're checking to see
   9874      * if either of these got set while we were suspended.
   9875      *
   9876      * We can't really avoid the #ifdefs here, because the fields don't
   9877      * exist when the feature is disabled.
   9878      */
   9879     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
   9880     cmp     r1, #0                      @ debugger enabled?
   9881     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
   9882     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
   9883     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
   9884 
   9885     orrs    r1, r1, r2
   9886     beq     2f
   9887 
   9888 1:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
   9889     str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
   9890     add     rPC, rPC, r9                @ update rPC
   9891     mov     r1, #1                      @ "want switch" = true
   9892     b       common_gotoBail             @ side exit
   9893 
   9894 2:
   9895     bx      lr                          @ nothing to do, return
   9896 
   9897 
   9898 /*
   9899  * The equivalent of "goto bail", this calls through the "bail handler".
   9900  *
   9901  * State registers will be saved to the "glue" area before bailing.
   9902  *
   9903  * On entry:
   9904  *  r1 is "bool changeInterp", indicating if we want to switch to the
   9905  *     other interpreter or just bail all the way out
   9906  */
   9907 common_gotoBail:
   9908     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
   9909     mov     r0, rGLUE                   @ r0<- glue ptr
   9910     b       dvmMterpStdBail             @ call(glue, changeInterp)
   9911 
   9912     @add     r1, r1, #1                  @ using (boolean+1)
   9913     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
   9914     @bl      _longjmp                    @ does not return
   9915     @bl      common_abort
   9916 
   9917 
   9918 /*
   9919  * Common code for method invocation with range.
   9920  *
   9921  * On entry:
   9922  *  r0 is "Method* methodToCall", the method we're trying to call
   9923  */
   9924 common_invokeMethodRange:
   9925 .LinvokeNewRange:
   9926     @ prepare to copy args to "outs" area of current frame
   9927     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
   9928     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
   9929     beq     .LinvokeArgsDone            @ if no args, skip the rest
   9930     FETCH(r1, 2)                        @ r1<- CCCC
   9931 
   9932     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
   9933     @ (very few methods have > 10 args; could unroll for common cases)
   9934     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
   9935     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
   9936     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
   9937 1:  ldr     r1, [r3], #4                @ val = *fp++
   9938     subs    r2, r2, #1                  @ count--
   9939     str     r1, [r10], #4               @ *outs++ = val
   9940     bne     1b                          @ ...while count != 0
   9941     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
   9942     b       .LinvokeArgsDone
   9943 
   9944 /*
   9945  * Common code for method invocation without range.
   9946  *
   9947  * On entry:
   9948  *  r0 is "Method* methodToCall", the method we're trying to call
   9949  */
   9950 common_invokeMethodNoRange:
   9951 .LinvokeNewNoRange:
   9952     @ prepare to copy args to "outs" area of current frame
   9953     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
   9954     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
   9955     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
   9956     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
   9957     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
   9958     beq     .LinvokeArgsDone
   9959 
   9960     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
   9961 .LinvokeNonRange:
   9962     rsb     r2, r2, #5                  @ r2<- 5-r2
   9963     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
   9964     bl      common_abort                @ (skipped due to ARM prefetch)
   9965 5:  and     ip, rINST, #0x0f00          @ isolate A
   9966     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
   9967     mov     r0, r0                      @ nop
   9968     str     r2, [r10, #-4]!             @ *--outs = vA
   9969 4:  and     ip, r1, #0xf000             @ isolate G
   9970     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
   9971     mov     r0, r0                      @ nop
   9972     str     r2, [r10, #-4]!             @ *--outs = vG
   9973 3:  and     ip, r1, #0x0f00             @ isolate F
   9974     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
   9975     mov     r0, r0                      @ nop
   9976     str     r2, [r10, #-4]!             @ *--outs = vF
   9977 2:  and     ip, r1, #0x00f0             @ isolate E
   9978     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
   9979     mov     r0, r0                      @ nop
   9980     str     r2, [r10, #-4]!             @ *--outs = vE
   9981 1:  and     ip, r1, #0x000f             @ isolate D
   9982     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
   9983     mov     r0, r0                      @ nop
   9984     str     r2, [r10, #-4]!             @ *--outs = vD
   9985 0:  @ fall through to .LinvokeArgsDone
   9986 
   9987 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
   9988     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
   9989     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
   9990     @ find space for the new stack frame, check for overflow
   9991     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
   9992     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
   9993     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
   9994 @    bl      common_dumpRegs
   9995     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
   9996     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
   9997     cmp     r3, r9                      @ bottom < interpStackEnd?
   9998     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
   9999     blo     .LstackOverflow             @ yes, this frame will overflow stack
   10000 
   10001     @ set up newSaveArea
   10002 #ifdef EASY_GDB
   10003     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
   10004     str     ip, [r10, #offStackSaveArea_prevSave]
   10005 #endif
   10006     str     rFP, [r10, #offStackSaveArea_prevFrame]
   10007     str     rPC, [r10, #offStackSaveArea_savedPc]
   10008 #if defined(WITH_JIT)
   10009     mov     r9, #0
   10010     str     r9, [r10, #offStackSaveArea_returnAddr]
   10011 #endif
   10012     str     r0, [r10, #offStackSaveArea_method]
   10013     tst     r3, #ACC_NATIVE
   10014     bne     .LinvokeNative
   10015 
   10016     /*
   10017     stmfd   sp!, {r0-r3}
   10018     bl      common_printNewline
   10019     mov     r0, rFP
   10020     mov     r1, #0
   10021     bl      dvmDumpFp
   10022     ldmfd   sp!, {r0-r3}
   10023     stmfd   sp!, {r0-r3}
   10024     mov     r0, r1
   10025     mov     r1, r10
   10026     bl      dvmDumpFp
   10027     bl      common_printNewline
   10028     ldmfd   sp!, {r0-r3}
   10029     */
   10030 
   10031     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
   10032     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
   10033     mov     rPC, r2                         @ publish new rPC
   10034     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
   10035 
   10036     @ Update "glue" values for the new method
   10037     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
   10038     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
   10039     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
   10040 #if defined(WITH_JIT)
   10041     GET_JIT_PROF_TABLE(r0)
   10042     mov     rFP, r1                         @ fp = newFp
   10043     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
   10044     mov     rINST, r9                       @ publish new rINST
   10045     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
   10046     cmp     r0,#0
   10047     bne     common_updateProfile
   10048     GOTO_OPCODE(ip)                         @ jump to next instruction
   10049 #else
   10050     mov     rFP, r1                         @ fp = newFp
   10051     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
   10052     mov     rINST, r9                       @ publish new rINST
   10053     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
   10054     GOTO_OPCODE(ip)                         @ jump to next instruction
   10055 #endif
   10056 
   10057 .LinvokeNative:
   10058     @ Prep for the native call
   10059     @ r0=methodToCall, r1=newFp, r10=newSaveArea
   10060     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
   10061     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
   10062     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
   10063     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
   10064     mov     r9, r3                      @ r9<- glue->self (preserve)
   10065 
   10066     mov     r2, r0                      @ r2<- methodToCall
   10067     mov     r0, r1                      @ r0<- newFp (points to args)
   10068     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
   10069 
   10070 #ifdef ASSIST_DEBUGGER
   10071     /* insert fake function header to help gdb find the stack frame */
   10072     b       .Lskip
   10073     .type   dalvik_mterp, %function
   10074 dalvik_mterp:
   10075     .fnstart
   10076     MTERP_ENTRY1
   10077     MTERP_ENTRY2
   10078 .Lskip:
   10079 #endif
   10080 
   10081     @mov     lr, pc                      @ set return addr
   10082     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
   10083     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
   10084 
   10085 #if defined(WITH_JIT)
   10086     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
   10087 #endif
   10088 
   10089     @ native return; r9=self, r10=newSaveArea
   10090     @ equivalent to dvmPopJniLocals
   10091     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
   10092     ldr     r1, [r9, #offThread_exception] @ check for exception
   10093 #if defined(WITH_JIT)
   10094     ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
   10095 #endif
   10096     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
   10097     cmp     r1, #0                      @ null?
   10098     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
   10099 #if defined(WITH_JIT)
   10100     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
   10101 #endif
   10102     bne     common_exceptionThrown      @ no, handle exception
   10103 
   10104     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   10105     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10106     GOTO_OPCODE(ip)                     @ jump to next instruction
   10107 
   10108 .LstackOverflow:    @ r0=methodToCall
   10109     mov     r1, r0                      @ r1<- methodToCall
   10110     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
   10111     bl      dvmHandleStackOverflow
   10112     b       common_exceptionThrown
   10113 #ifdef ASSIST_DEBUGGER
   10114     .fnend
   10115 #endif
   10116 
   10117 
   10118     /*
   10119      * Common code for method invocation, calling through "glue code".
   10120      *
   10121      * TODO: now that we have range and non-range invoke handlers, this
   10122      *       needs to be split into two.  Maybe just create entry points
   10123      *       that set r9 and jump here?
   10124      *
   10125      * On entry:
   10126      *  r0 is "Method* methodToCall", the method we're trying to call
   10127      *  r9 is "bool methodCallRange", indicating if this is a /range variant
   10128      */
   10129      .if    0
   10130 .LinvokeOld:
   10131     sub     sp, sp, #8                  @ space for args + pad
   10132     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
   10133     mov     r2, r0                      @ A2<- methodToCall
   10134     mov     r0, rGLUE                   @ A0<- glue
   10135     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
   10136     mov     r1, r9                      @ A1<- methodCallRange
   10137     mov     r3, rINST, lsr #8           @ A3<- AA
   10138     str     ip, [sp, #0]                @ A4<- ip
   10139     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
   10140     add     sp, sp, #8                  @ remove arg area
   10141     b       common_resumeAfterGlueCall  @ continue to next instruction
   10142     .endif
   10143 
   10144 
   10145 
   10146 /*
   10147  * Common code for handling a return instruction.
   10148  *
   10149  * This does not return.
   10150  */
   10151 common_returnFromMethod:
   10152 .LreturnNew:
   10153     mov     r0, #kInterpEntryReturn
   10154     mov     r9, #0
   10155     bl      common_periodicChecks
   10156 
   10157     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
   10158     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
   10159     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
   10160     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
   10161                                         @ r2<- method we're returning to
   10162     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
   10163     cmp     r2, #0                      @ is this a break frame?
   10164     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
   10165     mov     r1, #0                      @ "want switch" = false
   10166     beq     common_gotoBail             @ break frame, bail out completely
   10167 
   10168     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
   10169     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
   10170     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
   10171     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
   10172 #if defined(WITH_JIT)
   10173     ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
   10174     mov     rPC, r9                     @ publish new rPC
   10175     str     r1, [rGLUE, #offGlue_methodClassDex]
   10176     str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
   10177     cmp     r10, #0                      @ caller is compiled code
   10178     blxne   r10
   10179     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10180     GOTO_OPCODE(ip)                     @ jump to next instruction
   10181 #else
   10182     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10183     mov     rPC, r9                     @ publish new rPC
   10184     str     r1, [rGLUE, #offGlue_methodClassDex]
   10185     GOTO_OPCODE(ip)                     @ jump to next instruction
   10186 #endif
   10187 
   10188     /*
   10189      * Return handling, calls through "glue code".
   10190      */
   10191      .if    0
   10192 .LreturnOld:
   10193     SAVE_PC_FP_TO_GLUE()                @ export state
   10194     mov     r0, rGLUE                   @ arg to function
   10195     bl      dvmMterp_returnFromMethod
   10196     b       common_resumeAfterGlueCall
   10197     .endif
   10198 
   10199 
   10200 /*
   10201  * Somebody has thrown an exception.  Handle it.
   10202  *
   10203  * If the exception processing code returns to us (instead of falling
   10204  * out of the interpreter), continue with whatever the next instruction
   10205  * now happens to be.
   10206  *
   10207  * This does not return.
   10208  */
   10209      .global dvmMterpCommonExceptionThrown
   10210 dvmMterpCommonExceptionThrown:
   10211 common_exceptionThrown:
   10212 .LexceptionNew:
   10213     mov     r0, #kInterpEntryThrow
   10214     mov     r9, #0
   10215     bl      common_periodicChecks
   10216 
   10217     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
   10218     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
   10219     mov     r1, r10                     @ r1<- self
   10220     mov     r0, r9                      @ r0<- exception
   10221     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
   10222     mov     r3, #0                      @ r3<- NULL
   10223     str     r3, [r10, #offThread_exception] @ self->exception = NULL
   10224 
   10225     /* set up args and a local for "&fp" */
   10226     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
   10227     str     rFP, [sp, #-4]!             @ *--sp = fp
   10228     mov     ip, sp                      @ ip<- &fp
   10229     mov     r3, #0                      @ r3<- false
   10230     str     ip, [sp, #-4]!              @ *--sp = &fp
   10231     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
   10232     mov     r0, r10                     @ r0<- self
   10233     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
   10234     mov     r2, r9                      @ r2<- exception
   10235     sub     r1, rPC, r1                 @ r1<- pc - method->insns
   10236     mov     r1, r1, asr #1              @ r1<- offset in code units
   10237 
   10238     /* call, r0 gets catchRelPc (a code-unit offset) */
   10239     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
   10240 
   10241     /* fix earlier stack overflow if necessary; may trash rFP */
   10242     ldrb    r1, [r10, #offThread_stackOverflowed]
   10243     cmp     r1, #0                      @ did we overflow earlier?
   10244     beq     1f                          @ no, skip ahead
   10245     mov     rFP, r0                     @ save relPc result in rFP
   10246     mov     r0, r10                     @ r0<- self
   10247     mov     r1, r9                      @ r1<- exception
   10248     bl      dvmCleanupStackOverflow     @ call(self)
   10249     mov     r0, rFP                     @ restore result
   10250 1:
   10251 
   10252     /* update frame pointer and check result from dvmFindCatchBlock */
   10253     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
   10254     cmp     r0, #0                      @ is catchRelPc < 0?
   10255     add     sp, sp, #8                  @ restore stack
   10256     bmi     .LnotCaughtLocally
   10257 
   10258     /* adjust locals to match self->curFrame and updated PC */
   10259     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
   10260     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
   10261     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
   10262     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
   10263     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
   10264     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
   10265     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
   10266     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
   10267 
   10268     /* release the tracked alloc on the exception */
   10269     mov     r0, r9                      @ r0<- exception
   10270     mov     r1, r10                     @ r1<- self
   10271     bl      dvmReleaseTrackedAlloc      @ release the exception
   10272 
   10273     /* restore the exception if the handler wants it */
   10274     FETCH_INST()                        @ load rINST from rPC
   10275     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10276     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
   10277     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
   10278     GOTO_OPCODE(ip)                     @ jump to next instruction
   10279 
   10280 .LnotCaughtLocally: @ r9=exception, r10=self
   10281     /* fix stack overflow if necessary */
   10282     ldrb    r1, [r10, #offThread_stackOverflowed]
   10283     cmp     r1, #0                      @ did we overflow earlier?
   10284     movne   r0, r10                     @ if yes: r0<- self
   10285     movne   r1, r9                      @ if yes: r1<- exception
   10286     blne    dvmCleanupStackOverflow     @ if yes: call(self)
   10287 
   10288     @ may want to show "not caught locally" debug messages here
   10289 #if DVM_SHOW_EXCEPTION >= 2
   10290     /* call __android_log_print(prio, tag, format, ...) */
   10291     /* "Exception %s from %s:%d not caught locally" */
   10292     @ dvmLineNumFromPC(method, pc - method->insns)
   10293     ldr     r0, [rGLUE, #offGlue_method]
   10294     ldr     r1, [r0, #offMethod_insns]
   10295     sub     r1, rPC, r1
   10296     asr     r1, r1, #1
   10297     bl      dvmLineNumFromPC
   10298     str     r0, [sp, #-4]!
   10299     @ dvmGetMethodSourceFile(method)
   10300     ldr     r0, [rGLUE, #offGlue_method]
   10301     bl      dvmGetMethodSourceFile
   10302     str     r0, [sp, #-4]!
   10303     @ exception->clazz->descriptor
   10304     ldr     r3, [r9, #offObject_clazz]
   10305     ldr     r3, [r3, #offClassObject_descriptor]
   10306     @
   10307     ldr     r2, strExceptionNotCaughtLocally
   10308     ldr     r1, strLogTag
   10309     mov     r0, #3                      @ LOG_DEBUG
   10310     bl      __android_log_print
   10311 #endif
   10312     str     r9, [r10, #offThread_exception] @ restore exception
   10313     mov     r0, r9                      @ r0<- exception
   10314     mov     r1, r10                     @ r1<- self
   10315     bl      dvmReleaseTrackedAlloc      @ release the exception
   10316     mov     r1, #0                      @ "want switch" = false
   10317     b       common_gotoBail             @ bail out
   10318 
   10319 
   10320     /*
   10321      * Exception handling, calls through "glue code".
   10322      */
   10323     .if     0
   10324 .LexceptionOld:
   10325     SAVE_PC_FP_TO_GLUE()                @ export state
   10326     mov     r0, rGLUE                   @ arg to function
   10327     bl      dvmMterp_exceptionThrown
   10328     b       common_resumeAfterGlueCall
   10329     .endif
   10330 
   10331 
   10332 /*
   10333  * After returning from a "glued" function, pull out the updated
   10334  * values and start executing at the next instruction.
   10335  */
   10336 common_resumeAfterGlueCall:
   10337     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
   10338     FETCH_INST()                        @ load rINST from rPC
   10339     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10340     GOTO_OPCODE(ip)                     @ jump to next instruction
   10341 
   10342 /*
   10343  * Invalid array index.
   10344  */
   10345 common_errArrayIndex:
   10346     EXPORT_PC()
   10347     ldr     r0, strArrayIndexException
   10348     mov     r1, #0
   10349     bl      dvmThrowException
   10350     b       common_exceptionThrown
   10351 
   10352 /*
   10353  * Invalid array value.
   10354  */
   10355 common_errArrayStore:
   10356     EXPORT_PC()
   10357     ldr     r0, strArrayStoreException
   10358     mov     r1, #0
   10359     bl      dvmThrowException
   10360     b       common_exceptionThrown
   10361 
   10362 /*
   10363  * Integer divide or mod by zero.
   10364  */
   10365 common_errDivideByZero:
   10366     EXPORT_PC()
   10367     ldr     r0, strArithmeticException
   10368     ldr     r1, strDivideByZero
   10369     bl      dvmThrowException
   10370     b       common_exceptionThrown
   10371 
   10372 /*
   10373  * Attempt to allocate an array with a negative size.
   10374  */
   10375 common_errNegativeArraySize:
   10376     EXPORT_PC()
   10377     ldr     r0, strNegativeArraySizeException
   10378     mov     r1, #0
   10379     bl      dvmThrowException
   10380     b       common_exceptionThrown
   10381 
   10382 /*
   10383  * Invocation of a non-existent method.
   10384  */
   10385 common_errNoSuchMethod:
   10386     EXPORT_PC()
   10387     ldr     r0, strNoSuchMethodError
   10388     mov     r1, #0
   10389     bl      dvmThrowException
   10390     b       common_exceptionThrown
   10391 
   10392 /*
   10393  * We encountered a null object when we weren't expecting one.  We
   10394  * export the PC, throw a NullPointerException, and goto the exception
   10395  * processing code.
   10396  */
   10397 common_errNullObject:
   10398     EXPORT_PC()
   10399     ldr     r0, strNullPointerException
   10400     mov     r1, #0
   10401     bl      dvmThrowException
   10402     b       common_exceptionThrown
   10403 
   10404 /*
   10405  * For debugging, cause an immediate fault.  The source address will
   10406  * be in lr (use a bl instruction to jump here).
   10407  */
   10408 common_abort:
   10409     ldr     pc, .LdeadFood
   10410 .LdeadFood:
   10411     .word   0xdeadf00d
   10412 
   10413 /*
   10414  * Spit out a "we were here", preserving all registers.  (The attempt
   10415  * to save ip won't work, but we need to save an even number of
   10416  * registers for EABI 64-bit stack alignment.)
   10417  */
   10418     .macro  SQUEAK num
   10419 common_squeak\num:
   10420     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10421     ldr     r0, strSqueak
   10422     mov     r1, #\num
   10423     bl      printf
   10424     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10425     bx      lr
   10426     .endm
   10427 
   10428     SQUEAK  0
   10429     SQUEAK  1
   10430     SQUEAK  2
   10431     SQUEAK  3
   10432     SQUEAK  4
   10433     SQUEAK  5
   10434 
   10435 /*
   10436  * Spit out the number in r0, preserving registers.
   10437  */
   10438 common_printNum:
   10439     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10440     mov     r1, r0
   10441     ldr     r0, strSqueak
   10442     bl      printf
   10443     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10444     bx      lr
   10445 
   10446 /*
   10447  * Print a newline, preserving registers.
   10448  */
   10449 common_printNewline:
   10450     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10451     ldr     r0, strNewline
   10452     bl      printf
   10453     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10454     bx      lr
   10455 
   10456     /*
   10457      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
   10458      */
   10459 common_printHex:
   10460     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10461     mov     r1, r0
   10462     ldr     r0, strPrintHex
   10463     bl      printf
   10464     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10465     bx      lr
   10466 
   10467 /*
   10468  * Print the 64-bit quantity in r0-r1, preserving registers.
   10469  */
   10470 common_printLong:
   10471     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10472     mov     r3, r1
   10473     mov     r2, r0
   10474     ldr     r0, strPrintLong
   10475     bl      printf
   10476     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10477     bx      lr
   10478 
   10479 /*
   10480  * Print full method info.  Pass the Method* in r0.  Preserves regs.
   10481  */
   10482 common_printMethod:
   10483     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10484     bl      dvmMterpPrintMethod
   10485     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10486     bx      lr
   10487 
   10488 /*
   10489  * Call a C helper function that dumps regs and possibly some
   10490  * additional info.  Requires the C function to be compiled in.
   10491  */
   10492     .if     0
   10493 common_dumpRegs:
   10494     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10495     bl      dvmMterpDumpArmRegs
   10496     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10497     bx      lr
   10498     .endif
   10499 
   10500 #if 0
   10501 /*
   10502  * Experiment on VFP mode.
   10503  *
   10504  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
   10505  *
   10506  * Updates the bits specified by "mask", setting them to the values in "val".
   10507  */
   10508 setFPSCR:
   10509     and     r0, r0, r1                  @ make sure no stray bits are set
   10510     fmrx    r2, fpscr                   @ get VFP reg
   10511     mvn     r1, r1                      @ bit-invert mask
   10512     and     r2, r2, r1                  @ clear masked bits
   10513     orr     r2, r2, r0                  @ set specified bits
   10514     fmxr    fpscr, r2                   @ set VFP reg
   10515     mov     r0, r2                      @ return new value
   10516     bx      lr
   10517 
   10518     .align  2
   10519     .global dvmConfigureFP
   10520     .type   dvmConfigureFP, %function
   10521 dvmConfigureFP:
   10522     stmfd   sp!, {ip, lr}
   10523     /* 0x03000000 sets DN/FZ */
   10524     /* 0x00009f00 clears the six exception enable flags */
   10525     bl      common_squeak0
   10526     mov     r0, #0x03000000             @ r0<- 0x03000000
   10527     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
   10528     bl      setFPSCR
   10529     ldmfd   sp!, {ip, pc}
   10530 #endif
   10531 
   10532 
   10533 /*
   10534  * String references, must be close to the code that uses them.
   10535  */
   10536     .align  2
   10537 strArithmeticException:
   10538     .word   .LstrArithmeticException
   10539 strArrayIndexException:
   10540     .word   .LstrArrayIndexException
   10541 strArrayStoreException:
   10542     .word   .LstrArrayStoreException
   10543 strDivideByZero:
   10544     .word   .LstrDivideByZero
   10545 strNegativeArraySizeException:
   10546     .word   .LstrNegativeArraySizeException
   10547 strNoSuchMethodError:
   10548     .word   .LstrNoSuchMethodError
   10549 strNullPointerException:
   10550     .word   .LstrNullPointerException
   10551 
   10552 strLogTag:
   10553     .word   .LstrLogTag
   10554 strExceptionNotCaughtLocally:
   10555     .word   .LstrExceptionNotCaughtLocally
   10556 
   10557 strNewline:
   10558     .word   .LstrNewline
   10559 strSqueak:
   10560     .word   .LstrSqueak
   10561 strPrintHex:
   10562     .word   .LstrPrintHex
   10563 strPrintLong:
   10564     .word   .LstrPrintLong
   10565 
   10566 /*
   10567  * Zero-terminated ASCII string data.
   10568  *
   10569  * On ARM we have two choices: do like gcc does, and LDR from a .word
   10570  * with the address, or use an ADR pseudo-op to get the address
   10571  * directly.  ADR saves 4 bytes and an indirection, but it's using a
   10572  * PC-relative addressing mode and hence has a limited range, which
   10573  * makes it not work well with mergeable string sections.
   10574  */
   10575     .section .rodata.str1.4,"aMS",%progbits,1
   10576 
   10577 .LstrBadEntryPoint:
   10578     .asciz  "Bad entry point %d\n"
   10579 .LstrArithmeticException:
   10580     .asciz  "Ljava/lang/ArithmeticException;"
   10581 .LstrArrayIndexException:
   10582     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
   10583 .LstrArrayStoreException:
   10584     .asciz  "Ljava/lang/ArrayStoreException;"
   10585 .LstrClassCastException:
   10586     .asciz  "Ljava/lang/ClassCastException;"
   10587 .LstrDivideByZero:
   10588     .asciz  "divide by zero"
   10589 .LstrFilledNewArrayNotImpl:
   10590     .asciz  "filled-new-array only implemented for objects and 'int'"
   10591 .LstrInternalError:
   10592     .asciz  "Ljava/lang/InternalError;"
   10593 .LstrInstantiationError:
   10594     .asciz  "Ljava/lang/InstantiationError;"
   10595 .LstrNegativeArraySizeException:
   10596     .asciz  "Ljava/lang/NegativeArraySizeException;"
   10597 .LstrNoSuchMethodError:
   10598     .asciz  "Ljava/lang/NoSuchMethodError;"
   10599 .LstrNullPointerException:
   10600     .asciz  "Ljava/lang/NullPointerException;"
   10601 
   10602 .LstrLogTag:
   10603     .asciz  "mterp"
   10604 .LstrExceptionNotCaughtLocally:
   10605     .asciz  "Exception %s from %s:%d not caught locally\n"
   10606 
   10607 .LstrNewline:
   10608     .asciz  "\n"
   10609 .LstrSqueak:
   10610     .asciz  "<%d>"
   10611 .LstrPrintHex:
   10612     .asciz  "<0x%x>"
   10613 .LstrPrintLong:
   10614     .asciz  "<%lld>"
   10615 
   10616