Home | History | Annotate | Download | only in out
      1 /*
      2  * This file was generated automatically by gen-mterp.py for 'armv4t'.
      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: armv5te/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      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
   1309      * on what value we'd like to return when one of the operands is NaN.
   1310      *
   1311      * The operation we're implementing is:
   1312      *   if (x == y)
   1313      *     return 0;
   1314      *   else if (x < y)
   1315      *     return -1;
   1316      *   else if (x > y)
   1317      *     return 1;
   1318      *   else
   1319      *     return {-1,1};  // one or both operands was NaN
   1320      *
   1321      * The straightforward implementation requires 3 calls to functions
   1322      * that return a result in r0.  We can do it with two calls if our
   1323      * EABI library supports __aeabi_cfcmple (only one if we want to check
   1324      * for NaN directly):
   1325      *   check x <= y
   1326      *     if <, return -1
   1327      *     if ==, return 0
   1328      *   check y <= x
   1329      *     if <, return 1
   1330      *   return {-1,1}
   1331      *
   1332      * for: cmpl-float, cmpg-float
   1333      */
   1334     /* op vAA, vBB, vCC */
   1335     FETCH(r0, 1)                        @ r0<- CCBB
   1336     and     r2, r0, #255                @ r2<- BB
   1337     mov     r3, r0, lsr #8              @ r3<- CC
   1338     GET_VREG(r9, r2)                    @ r9<- vBB
   1339     GET_VREG(r10, r3)                   @ r10<- vCC
   1340     mov     r0, r9                      @ copy to arg registers
   1341     mov     r1, r10
   1342     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
   1343     bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
   1344     mvncc   r1, #0                      @ (less than) r1<- -1
   1345     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
   1346 .LOP_CMPL_FLOAT_finish:
   1347     mov     r3, rINST, lsr #8           @ r3<- AA
   1348     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1349     SET_VREG(r1, r3)                    @ vAA<- r1
   1350     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1351     GOTO_OPCODE(ip)                     @ jump to next instruction
   1352 
   1353 /* ------------------------------ */
   1354     .balign 64
   1355 .L_OP_CMPG_FLOAT: /* 0x2e */
   1356 /* File: armv5te/OP_CMPG_FLOAT.S */
   1357 /* File: armv5te/OP_CMPL_FLOAT.S */
   1358     /*
   1359      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1360      * destination register based on the results of the comparison.
   1361      *
   1362      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
   1363      * on what value we'd like to return when one of the operands is NaN.
   1364      *
   1365      * The operation we're implementing is:
   1366      *   if (x == y)
   1367      *     return 0;
   1368      *   else if (x < y)
   1369      *     return -1;
   1370      *   else if (x > y)
   1371      *     return 1;
   1372      *   else
   1373      *     return {-1,1};  // one or both operands was NaN
   1374      *
   1375      * The straightforward implementation requires 3 calls to functions
   1376      * that return a result in r0.  We can do it with two calls if our
   1377      * EABI library supports __aeabi_cfcmple (only one if we want to check
   1378      * for NaN directly):
   1379      *   check x <= y
   1380      *     if <, return -1
   1381      *     if ==, return 0
   1382      *   check y <= x
   1383      *     if <, return 1
   1384      *   return {-1,1}
   1385      *
   1386      * for: cmpl-float, cmpg-float
   1387      */
   1388     /* op vAA, vBB, vCC */
   1389     FETCH(r0, 1)                        @ r0<- CCBB
   1390     and     r2, r0, #255                @ r2<- BB
   1391     mov     r3, r0, lsr #8              @ r3<- CC
   1392     GET_VREG(r9, r2)                    @ r9<- vBB
   1393     GET_VREG(r10, r3)                   @ r10<- vCC
   1394     mov     r0, r9                      @ copy to arg registers
   1395     mov     r1, r10
   1396     bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
   1397     bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
   1398     mvncc   r1, #0                      @ (less than) r1<- -1
   1399     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
   1400 .LOP_CMPG_FLOAT_finish:
   1401     mov     r3, rINST, lsr #8           @ r3<- AA
   1402     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1403     SET_VREG(r1, r3)                    @ vAA<- r1
   1404     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1405     GOTO_OPCODE(ip)                     @ jump to next instruction
   1406 
   1407 
   1408 /* ------------------------------ */
   1409     .balign 64
   1410 .L_OP_CMPL_DOUBLE: /* 0x2f */
   1411 /* File: armv5te/OP_CMPL_DOUBLE.S */
   1412     /*
   1413      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1414      * destination register based on the results of the comparison.
   1415      *
   1416      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
   1417      * on what value we'd like to return when one of the operands is NaN.
   1418      *
   1419      * See OP_CMPL_FLOAT for an explanation.
   1420      *
   1421      * For: cmpl-double, cmpg-double
   1422      */
   1423     /* op vAA, vBB, vCC */
   1424     FETCH(r0, 1)                        @ r0<- CCBB
   1425     and     r9, r0, #255                @ r9<- BB
   1426     mov     r10, r0, lsr #8             @ r10<- CC
   1427     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
   1428     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
   1429     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   1430     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
   1431     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
   1432     bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
   1433     mvncc   r1, #0                      @ (less than) r1<- -1
   1434     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
   1435 .LOP_CMPL_DOUBLE_finish:
   1436     mov     r3, rINST, lsr #8           @ r3<- AA
   1437     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1438     SET_VREG(r1, r3)                    @ vAA<- r1
   1439     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1440     GOTO_OPCODE(ip)                     @ jump to next instruction
   1441 
   1442 /* ------------------------------ */
   1443     .balign 64
   1444 .L_OP_CMPG_DOUBLE: /* 0x30 */
   1445 /* File: armv5te/OP_CMPG_DOUBLE.S */
   1446 /* File: armv5te/OP_CMPL_DOUBLE.S */
   1447     /*
   1448      * Compare two floating-point values.  Puts 0, 1, or -1 into the
   1449      * destination register based on the results of the comparison.
   1450      *
   1451      * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
   1452      * on what value we'd like to return when one of the operands is NaN.
   1453      *
   1454      * See OP_CMPL_FLOAT for an explanation.
   1455      *
   1456      * For: cmpl-double, cmpg-double
   1457      */
   1458     /* op vAA, vBB, vCC */
   1459     FETCH(r0, 1)                        @ r0<- CCBB
   1460     and     r9, r0, #255                @ r9<- BB
   1461     mov     r10, r0, lsr #8             @ r10<- CC
   1462     add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
   1463     add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
   1464     ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   1465     ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
   1466     bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
   1467     bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
   1468     mvncc   r1, #0                      @ (less than) r1<- -1
   1469     moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
   1470 .LOP_CMPG_DOUBLE_finish:
   1471     mov     r3, rINST, lsr #8           @ r3<- AA
   1472     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   1473     SET_VREG(r1, r3)                    @ vAA<- r1
   1474     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1475     GOTO_OPCODE(ip)                     @ jump to next instruction
   1476 
   1477 
   1478 /* ------------------------------ */
   1479     .balign 64
   1480 .L_OP_CMP_LONG: /* 0x31 */
   1481 /* File: armv5te/OP_CMP_LONG.S */
   1482     /*
   1483      * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
   1484      * register based on the results of the comparison.
   1485      *
   1486      * We load the full values with LDM, but in practice many values could
   1487      * be resolved by only looking at the high word.  This could be made
   1488      * faster or slower by splitting the LDM into a pair of LDRs.
   1489      *
   1490      * If we just wanted to set condition flags, we could do this:
   1491      *  subs    ip, r0, r2
   1492      *  sbcs    ip, r1, r3
   1493      *  subeqs  ip, r0, r2
   1494      * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
   1495      * integer value, which we can do with 2 conditional mov/mvn instructions
   1496      * (set 1, set -1; if they're equal we already have 0 in ip), giving
   1497      * us a constant 5-cycle path plus a branch at the end to the
   1498      * instruction epilogue code.  The multi-compare approach below needs
   1499      * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
   1500      * in the worst case (the 64-bit values are equal).
   1501      */
   1502     /* cmp-long vAA, vBB, vCC */
   1503     FETCH(r0, 1)                        @ r0<- CCBB
   1504     mov     r9, rINST, lsr #8           @ r9<- AA
   1505     and     r2, r0, #255                @ r2<- BB
   1506     mov     r3, r0, lsr #8              @ r3<- CC
   1507     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   1508     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   1509     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   1510     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   1511     cmp     r1, r3                      @ compare (vBB+1, vCC+1)
   1512     blt     .LOP_CMP_LONG_less            @ signed compare on high part
   1513     bgt     .LOP_CMP_LONG_greater
   1514     subs    r1, r0, r2                  @ r1<- r0 - r2
   1515     bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
   1516     bne     .LOP_CMP_LONG_less
   1517     b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
   1518 
   1519 /* ------------------------------ */
   1520     .balign 64
   1521 .L_OP_IF_EQ: /* 0x32 */
   1522 /* File: armv5te/OP_IF_EQ.S */
   1523 /* File: armv5te/bincmp.S */
   1524     /*
   1525      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1526      * fragment that specifies the *reverse* comparison to perform, e.g.
   1527      * for "if-le" you would use "gt".
   1528      *
   1529      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1530      */
   1531     /* if-cmp vA, vB, +CCCC */
   1532     mov     r0, rINST, lsr #8           @ r0<- A+
   1533     mov     r1, rINST, lsr #12          @ r1<- B
   1534     and     r0, r0, #15
   1535     GET_VREG(r3, r1)                    @ r3<- vB
   1536     GET_VREG(r2, r0)                    @ r2<- vA
   1537     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1538     cmp     r2, r3                      @ compare (vA, vB)
   1539     bne  1f                      @ branch to 1 if comparison failed
   1540     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1541     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1542     bmi     common_backwardBranch       @ yes, do periodic checks
   1543 1:
   1544 #if defined(WITH_JIT)
   1545     GET_JIT_PROF_TABLE(r0)
   1546     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1547     b        common_testUpdateProfile
   1548 #else
   1549     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1550     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1551     GOTO_OPCODE(ip)                     @ jump to next instruction
   1552 #endif
   1553 
   1554 
   1555 /* ------------------------------ */
   1556     .balign 64
   1557 .L_OP_IF_NE: /* 0x33 */
   1558 /* File: armv5te/OP_IF_NE.S */
   1559 /* File: armv5te/bincmp.S */
   1560     /*
   1561      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1562      * fragment that specifies the *reverse* comparison to perform, e.g.
   1563      * for "if-le" you would use "gt".
   1564      *
   1565      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1566      */
   1567     /* if-cmp vA, vB, +CCCC */
   1568     mov     r0, rINST, lsr #8           @ r0<- A+
   1569     mov     r1, rINST, lsr #12          @ r1<- B
   1570     and     r0, r0, #15
   1571     GET_VREG(r3, r1)                    @ r3<- vB
   1572     GET_VREG(r2, r0)                    @ r2<- vA
   1573     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1574     cmp     r2, r3                      @ compare (vA, vB)
   1575     beq  1f                      @ branch to 1 if comparison failed
   1576     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1577     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1578     bmi     common_backwardBranch       @ yes, do periodic checks
   1579 1:
   1580 #if defined(WITH_JIT)
   1581     GET_JIT_PROF_TABLE(r0)
   1582     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1583     b        common_testUpdateProfile
   1584 #else
   1585     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1586     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1587     GOTO_OPCODE(ip)                     @ jump to next instruction
   1588 #endif
   1589 
   1590 
   1591 /* ------------------------------ */
   1592     .balign 64
   1593 .L_OP_IF_LT: /* 0x34 */
   1594 /* File: armv5te/OP_IF_LT.S */
   1595 /* File: armv5te/bincmp.S */
   1596     /*
   1597      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1598      * fragment that specifies the *reverse* comparison to perform, e.g.
   1599      * for "if-le" you would use "gt".
   1600      *
   1601      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1602      */
   1603     /* if-cmp vA, vB, +CCCC */
   1604     mov     r0, rINST, lsr #8           @ r0<- A+
   1605     mov     r1, rINST, lsr #12          @ r1<- B
   1606     and     r0, r0, #15
   1607     GET_VREG(r3, r1)                    @ r3<- vB
   1608     GET_VREG(r2, r0)                    @ r2<- vA
   1609     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1610     cmp     r2, r3                      @ compare (vA, vB)
   1611     bge  1f                      @ branch to 1 if comparison failed
   1612     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1613     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1614     bmi     common_backwardBranch       @ yes, do periodic checks
   1615 1:
   1616 #if defined(WITH_JIT)
   1617     GET_JIT_PROF_TABLE(r0)
   1618     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1619     b        common_testUpdateProfile
   1620 #else
   1621     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1622     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1623     GOTO_OPCODE(ip)                     @ jump to next instruction
   1624 #endif
   1625 
   1626 
   1627 /* ------------------------------ */
   1628     .balign 64
   1629 .L_OP_IF_GE: /* 0x35 */
   1630 /* File: armv5te/OP_IF_GE.S */
   1631 /* File: armv5te/bincmp.S */
   1632     /*
   1633      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1634      * fragment that specifies the *reverse* comparison to perform, e.g.
   1635      * for "if-le" you would use "gt".
   1636      *
   1637      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1638      */
   1639     /* if-cmp vA, vB, +CCCC */
   1640     mov     r0, rINST, lsr #8           @ r0<- A+
   1641     mov     r1, rINST, lsr #12          @ r1<- B
   1642     and     r0, r0, #15
   1643     GET_VREG(r3, r1)                    @ r3<- vB
   1644     GET_VREG(r2, r0)                    @ r2<- vA
   1645     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1646     cmp     r2, r3                      @ compare (vA, vB)
   1647     blt  1f                      @ branch to 1 if comparison failed
   1648     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1649     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1650     bmi     common_backwardBranch       @ yes, do periodic checks
   1651 1:
   1652 #if defined(WITH_JIT)
   1653     GET_JIT_PROF_TABLE(r0)
   1654     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1655     b        common_testUpdateProfile
   1656 #else
   1657     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1658     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1659     GOTO_OPCODE(ip)                     @ jump to next instruction
   1660 #endif
   1661 
   1662 
   1663 /* ------------------------------ */
   1664     .balign 64
   1665 .L_OP_IF_GT: /* 0x36 */
   1666 /* File: armv5te/OP_IF_GT.S */
   1667 /* File: armv5te/bincmp.S */
   1668     /*
   1669      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1670      * fragment that specifies the *reverse* comparison to perform, e.g.
   1671      * for "if-le" you would use "gt".
   1672      *
   1673      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1674      */
   1675     /* if-cmp vA, vB, +CCCC */
   1676     mov     r0, rINST, lsr #8           @ r0<- A+
   1677     mov     r1, rINST, lsr #12          @ r1<- B
   1678     and     r0, r0, #15
   1679     GET_VREG(r3, r1)                    @ r3<- vB
   1680     GET_VREG(r2, r0)                    @ r2<- vA
   1681     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1682     cmp     r2, r3                      @ compare (vA, vB)
   1683     ble  1f                      @ branch to 1 if comparison failed
   1684     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1685     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1686     bmi     common_backwardBranch       @ yes, do periodic checks
   1687 1:
   1688 #if defined(WITH_JIT)
   1689     GET_JIT_PROF_TABLE(r0)
   1690     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1691     b        common_testUpdateProfile
   1692 #else
   1693     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1694     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1695     GOTO_OPCODE(ip)                     @ jump to next instruction
   1696 #endif
   1697 
   1698 
   1699 /* ------------------------------ */
   1700     .balign 64
   1701 .L_OP_IF_LE: /* 0x37 */
   1702 /* File: armv5te/OP_IF_LE.S */
   1703 /* File: armv5te/bincmp.S */
   1704     /*
   1705      * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
   1706      * fragment that specifies the *reverse* comparison to perform, e.g.
   1707      * for "if-le" you would use "gt".
   1708      *
   1709      * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
   1710      */
   1711     /* if-cmp vA, vB, +CCCC */
   1712     mov     r0, rINST, lsr #8           @ r0<- A+
   1713     mov     r1, rINST, lsr #12          @ r1<- B
   1714     and     r0, r0, #15
   1715     GET_VREG(r3, r1)                    @ r3<- vB
   1716     GET_VREG(r2, r0)                    @ r2<- vA
   1717     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1718     cmp     r2, r3                      @ compare (vA, vB)
   1719     bgt  1f                      @ branch to 1 if comparison failed
   1720     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1721     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1722     bmi     common_backwardBranch       @ yes, do periodic checks
   1723 1:
   1724 #if defined(WITH_JIT)
   1725     GET_JIT_PROF_TABLE(r0)
   1726     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1727     b        common_testUpdateProfile
   1728 #else
   1729     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1730     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1731     GOTO_OPCODE(ip)                     @ jump to next instruction
   1732 #endif
   1733 
   1734 
   1735 /* ------------------------------ */
   1736     .balign 64
   1737 .L_OP_IF_EQZ: /* 0x38 */
   1738 /* File: armv5te/OP_IF_EQZ.S */
   1739 /* File: armv5te/zcmp.S */
   1740     /*
   1741      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1742      * fragment that specifies the *reverse* comparison to perform, e.g.
   1743      * for "if-le" you would use "gt".
   1744      *
   1745      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1746      */
   1747     /* if-cmp vAA, +BBBB */
   1748     mov     r0, rINST, lsr #8           @ r0<- AA
   1749     GET_VREG(r2, r0)                    @ r2<- vAA
   1750     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1751     cmp     r2, #0                      @ compare (vA, 0)
   1752     bne  1f                      @ branch to 1 if comparison failed
   1753     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1754     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1755     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1756 1:
   1757 #if defined(WITH_JIT)
   1758     GET_JIT_PROF_TABLE(r0)
   1759     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1760     cmp     r0,#0
   1761     bne     common_updateProfile
   1762     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1763     GOTO_OPCODE(ip)                     @ jump to next instruction
   1764 #else
   1765     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1766     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1767     GOTO_OPCODE(ip)                     @ jump to next instruction
   1768 #endif
   1769 
   1770 
   1771 /* ------------------------------ */
   1772     .balign 64
   1773 .L_OP_IF_NEZ: /* 0x39 */
   1774 /* File: armv5te/OP_IF_NEZ.S */
   1775 /* File: armv5te/zcmp.S */
   1776     /*
   1777      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1778      * fragment that specifies the *reverse* comparison to perform, e.g.
   1779      * for "if-le" you would use "gt".
   1780      *
   1781      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1782      */
   1783     /* if-cmp vAA, +BBBB */
   1784     mov     r0, rINST, lsr #8           @ r0<- AA
   1785     GET_VREG(r2, r0)                    @ r2<- vAA
   1786     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1787     cmp     r2, #0                      @ compare (vA, 0)
   1788     beq  1f                      @ branch to 1 if comparison failed
   1789     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1790     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1791     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1792 1:
   1793 #if defined(WITH_JIT)
   1794     GET_JIT_PROF_TABLE(r0)
   1795     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1796     cmp     r0,#0
   1797     bne     common_updateProfile
   1798     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1799     GOTO_OPCODE(ip)                     @ jump to next instruction
   1800 #else
   1801     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1802     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1803     GOTO_OPCODE(ip)                     @ jump to next instruction
   1804 #endif
   1805 
   1806 
   1807 /* ------------------------------ */
   1808     .balign 64
   1809 .L_OP_IF_LTZ: /* 0x3a */
   1810 /* File: armv5te/OP_IF_LTZ.S */
   1811 /* File: armv5te/zcmp.S */
   1812     /*
   1813      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1814      * fragment that specifies the *reverse* comparison to perform, e.g.
   1815      * for "if-le" you would use "gt".
   1816      *
   1817      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1818      */
   1819     /* if-cmp vAA, +BBBB */
   1820     mov     r0, rINST, lsr #8           @ r0<- AA
   1821     GET_VREG(r2, r0)                    @ r2<- vAA
   1822     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1823     cmp     r2, #0                      @ compare (vA, 0)
   1824     bge  1f                      @ branch to 1 if comparison failed
   1825     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1826     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1827     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1828 1:
   1829 #if defined(WITH_JIT)
   1830     GET_JIT_PROF_TABLE(r0)
   1831     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1832     cmp     r0,#0
   1833     bne     common_updateProfile
   1834     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1835     GOTO_OPCODE(ip)                     @ jump to next instruction
   1836 #else
   1837     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1838     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1839     GOTO_OPCODE(ip)                     @ jump to next instruction
   1840 #endif
   1841 
   1842 
   1843 /* ------------------------------ */
   1844     .balign 64
   1845 .L_OP_IF_GEZ: /* 0x3b */
   1846 /* File: armv5te/OP_IF_GEZ.S */
   1847 /* File: armv5te/zcmp.S */
   1848     /*
   1849      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1850      * fragment that specifies the *reverse* comparison to perform, e.g.
   1851      * for "if-le" you would use "gt".
   1852      *
   1853      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1854      */
   1855     /* if-cmp vAA, +BBBB */
   1856     mov     r0, rINST, lsr #8           @ r0<- AA
   1857     GET_VREG(r2, r0)                    @ r2<- vAA
   1858     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1859     cmp     r2, #0                      @ compare (vA, 0)
   1860     blt  1f                      @ branch to 1 if comparison failed
   1861     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1862     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1863     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1864 1:
   1865 #if defined(WITH_JIT)
   1866     GET_JIT_PROF_TABLE(r0)
   1867     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1868     cmp     r0,#0
   1869     bne     common_updateProfile
   1870     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1871     GOTO_OPCODE(ip)                     @ jump to next instruction
   1872 #else
   1873     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1874     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1875     GOTO_OPCODE(ip)                     @ jump to next instruction
   1876 #endif
   1877 
   1878 
   1879 /* ------------------------------ */
   1880     .balign 64
   1881 .L_OP_IF_GTZ: /* 0x3c */
   1882 /* File: armv5te/OP_IF_GTZ.S */
   1883 /* File: armv5te/zcmp.S */
   1884     /*
   1885      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1886      * fragment that specifies the *reverse* comparison to perform, e.g.
   1887      * for "if-le" you would use "gt".
   1888      *
   1889      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1890      */
   1891     /* if-cmp vAA, +BBBB */
   1892     mov     r0, rINST, lsr #8           @ r0<- AA
   1893     GET_VREG(r2, r0)                    @ r2<- vAA
   1894     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1895     cmp     r2, #0                      @ compare (vA, 0)
   1896     ble  1f                      @ branch to 1 if comparison failed
   1897     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1898     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1899     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1900 1:
   1901 #if defined(WITH_JIT)
   1902     GET_JIT_PROF_TABLE(r0)
   1903     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1904     cmp     r0,#0
   1905     bne     common_updateProfile
   1906     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1907     GOTO_OPCODE(ip)                     @ jump to next instruction
   1908 #else
   1909     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1910     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1911     GOTO_OPCODE(ip)                     @ jump to next instruction
   1912 #endif
   1913 
   1914 
   1915 /* ------------------------------ */
   1916     .balign 64
   1917 .L_OP_IF_LEZ: /* 0x3d */
   1918 /* File: armv5te/OP_IF_LEZ.S */
   1919 /* File: armv5te/zcmp.S */
   1920     /*
   1921      * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
   1922      * fragment that specifies the *reverse* comparison to perform, e.g.
   1923      * for "if-le" you would use "gt".
   1924      *
   1925      * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
   1926      */
   1927     /* if-cmp vAA, +BBBB */
   1928     mov     r0, rINST, lsr #8           @ r0<- AA
   1929     GET_VREG(r2, r0)                    @ r2<- vAA
   1930     mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
   1931     cmp     r2, #0                      @ compare (vA, 0)
   1932     bgt  1f                      @ branch to 1 if comparison failed
   1933     FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
   1934     movs    r9, r9, asl #1              @ convert to bytes, check sign
   1935     bmi     common_backwardBranch       @ backward branch, do periodic checks
   1936 1:
   1937 #if defined(WITH_JIT)
   1938     GET_JIT_PROF_TABLE(r0)
   1939     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1940     cmp     r0,#0
   1941     bne     common_updateProfile
   1942     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1943     GOTO_OPCODE(ip)                     @ jump to next instruction
   1944 #else
   1945     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   1946     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   1947     GOTO_OPCODE(ip)                     @ jump to next instruction
   1948 #endif
   1949 
   1950 
   1951 /* ------------------------------ */
   1952     .balign 64
   1953 .L_OP_UNUSED_3E: /* 0x3e */
   1954 /* File: armv5te/OP_UNUSED_3E.S */
   1955 /* File: armv5te/unused.S */
   1956     bl      common_abort
   1957 
   1958 
   1959 /* ------------------------------ */
   1960     .balign 64
   1961 .L_OP_UNUSED_3F: /* 0x3f */
   1962 /* File: armv5te/OP_UNUSED_3F.S */
   1963 /* File: armv5te/unused.S */
   1964     bl      common_abort
   1965 
   1966 
   1967 /* ------------------------------ */
   1968     .balign 64
   1969 .L_OP_UNUSED_40: /* 0x40 */
   1970 /* File: armv5te/OP_UNUSED_40.S */
   1971 /* File: armv5te/unused.S */
   1972     bl      common_abort
   1973 
   1974 
   1975 /* ------------------------------ */
   1976     .balign 64
   1977 .L_OP_UNUSED_41: /* 0x41 */
   1978 /* File: armv5te/OP_UNUSED_41.S */
   1979 /* File: armv5te/unused.S */
   1980     bl      common_abort
   1981 
   1982 
   1983 /* ------------------------------ */
   1984     .balign 64
   1985 .L_OP_UNUSED_42: /* 0x42 */
   1986 /* File: armv5te/OP_UNUSED_42.S */
   1987 /* File: armv5te/unused.S */
   1988     bl      common_abort
   1989 
   1990 
   1991 /* ------------------------------ */
   1992     .balign 64
   1993 .L_OP_UNUSED_43: /* 0x43 */
   1994 /* File: armv5te/OP_UNUSED_43.S */
   1995 /* File: armv5te/unused.S */
   1996     bl      common_abort
   1997 
   1998 
   1999 /* ------------------------------ */
   2000     .balign 64
   2001 .L_OP_AGET: /* 0x44 */
   2002 /* File: armv5te/OP_AGET.S */
   2003     /*
   2004      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2005      *
   2006      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2007      * instructions.  We use a pair of FETCH_Bs instead.
   2008      *
   2009      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2010      */
   2011     /* op vAA, vBB, vCC */
   2012     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2013     mov     r9, rINST, lsr #8           @ r9<- AA
   2014     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2015     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2016     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2017     cmp     r0, #0                      @ null array object?
   2018     beq     common_errNullObject        @ yes, bail
   2019     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2020     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
   2021     cmp     r1, r3                      @ compare unsigned index, length
   2022     bcs     common_errArrayIndex        @ index >= length, bail
   2023     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2024     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2025     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2026     SET_VREG(r2, r9)                    @ vAA<- r2
   2027     GOTO_OPCODE(ip)                     @ jump to next instruction
   2028 
   2029 /* ------------------------------ */
   2030     .balign 64
   2031 .L_OP_AGET_WIDE: /* 0x45 */
   2032 /* File: armv4t/OP_AGET_WIDE.S */
   2033     /*
   2034      * Array get, 64 bits.  vAA <- vBB[vCC].
   2035      *
   2036      * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
   2037      */
   2038     /* aget-wide vAA, vBB, vCC */
   2039     FETCH(r0, 1)                        @ r0<- CCBB
   2040     mov     r9, rINST, lsr #8           @ r9<- AA
   2041     and     r2, r0, #255                @ r2<- BB
   2042     mov     r3, r0, lsr #8              @ r3<- CC
   2043     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2044     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2045     cmp     r0, #0                      @ null array object?
   2046     beq     common_errNullObject        @ yes, bail
   2047     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2048     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
   2049     cmp     r1, r3                      @ compare unsigned index, length
   2050     bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
   2051     b       common_errArrayIndex        @ index >= length, bail
   2052     @ May want to swap the order of these two branches depending on how the
   2053     @ branch prediction (if any) handles conditional forward branches vs.
   2054     @ unconditional forward branches.
   2055 
   2056 /* ------------------------------ */
   2057     .balign 64
   2058 .L_OP_AGET_OBJECT: /* 0x46 */
   2059 /* File: armv5te/OP_AGET_OBJECT.S */
   2060 /* File: armv5te/OP_AGET.S */
   2061     /*
   2062      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2063      *
   2064      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2065      * instructions.  We use a pair of FETCH_Bs instead.
   2066      *
   2067      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2068      */
   2069     /* op vAA, vBB, vCC */
   2070     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2071     mov     r9, rINST, lsr #8           @ r9<- AA
   2072     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2073     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2074     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2075     cmp     r0, #0                      @ null array object?
   2076     beq     common_errNullObject        @ yes, bail
   2077     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2078     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
   2079     cmp     r1, r3                      @ compare unsigned index, length
   2080     bcs     common_errArrayIndex        @ index >= length, bail
   2081     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2082     ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2083     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2084     SET_VREG(r2, r9)                    @ vAA<- r2
   2085     GOTO_OPCODE(ip)                     @ jump to next instruction
   2086 
   2087 
   2088 /* ------------------------------ */
   2089     .balign 64
   2090 .L_OP_AGET_BOOLEAN: /* 0x47 */
   2091 /* File: armv5te/OP_AGET_BOOLEAN.S */
   2092 /* File: armv5te/OP_AGET.S */
   2093     /*
   2094      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2095      *
   2096      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2097      * instructions.  We use a pair of FETCH_Bs instead.
   2098      *
   2099      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2100      */
   2101     /* op vAA, vBB, vCC */
   2102     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2103     mov     r9, rINST, lsr #8           @ r9<- AA
   2104     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2105     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2106     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2107     cmp     r0, #0                      @ null array object?
   2108     beq     common_errNullObject        @ yes, bail
   2109     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2110     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2111     cmp     r1, r3                      @ compare unsigned index, length
   2112     bcs     common_errArrayIndex        @ index >= length, bail
   2113     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2114     ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2115     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2116     SET_VREG(r2, r9)                    @ vAA<- r2
   2117     GOTO_OPCODE(ip)                     @ jump to next instruction
   2118 
   2119 
   2120 /* ------------------------------ */
   2121     .balign 64
   2122 .L_OP_AGET_BYTE: /* 0x48 */
   2123 /* File: armv5te/OP_AGET_BYTE.S */
   2124 /* File: armv5te/OP_AGET.S */
   2125     /*
   2126      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2127      *
   2128      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2129      * instructions.  We use a pair of FETCH_Bs instead.
   2130      *
   2131      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2132      */
   2133     /* op vAA, vBB, vCC */
   2134     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2135     mov     r9, rINST, lsr #8           @ r9<- AA
   2136     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2137     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2138     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2139     cmp     r0, #0                      @ null array object?
   2140     beq     common_errNullObject        @ yes, bail
   2141     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2142     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2143     cmp     r1, r3                      @ compare unsigned index, length
   2144     bcs     common_errArrayIndex        @ index >= length, bail
   2145     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2146     ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2147     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2148     SET_VREG(r2, r9)                    @ vAA<- r2
   2149     GOTO_OPCODE(ip)                     @ jump to next instruction
   2150 
   2151 
   2152 /* ------------------------------ */
   2153     .balign 64
   2154 .L_OP_AGET_CHAR: /* 0x49 */
   2155 /* File: armv5te/OP_AGET_CHAR.S */
   2156 /* File: armv5te/OP_AGET.S */
   2157     /*
   2158      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2159      *
   2160      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2161      * instructions.  We use a pair of FETCH_Bs instead.
   2162      *
   2163      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2164      */
   2165     /* op vAA, vBB, vCC */
   2166     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2167     mov     r9, rINST, lsr #8           @ r9<- AA
   2168     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2169     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2170     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2171     cmp     r0, #0                      @ null array object?
   2172     beq     common_errNullObject        @ yes, bail
   2173     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2174     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2175     cmp     r1, r3                      @ compare unsigned index, length
   2176     bcs     common_errArrayIndex        @ index >= length, bail
   2177     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2178     ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2179     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2180     SET_VREG(r2, r9)                    @ vAA<- r2
   2181     GOTO_OPCODE(ip)                     @ jump to next instruction
   2182 
   2183 
   2184 /* ------------------------------ */
   2185     .balign 64
   2186 .L_OP_AGET_SHORT: /* 0x4a */
   2187 /* File: armv5te/OP_AGET_SHORT.S */
   2188 /* File: armv5te/OP_AGET.S */
   2189     /*
   2190      * Array get, 32 bits or less.  vAA <- vBB[vCC].
   2191      *
   2192      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2193      * instructions.  We use a pair of FETCH_Bs instead.
   2194      *
   2195      * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
   2196      */
   2197     /* op vAA, vBB, vCC */
   2198     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2199     mov     r9, rINST, lsr #8           @ r9<- AA
   2200     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2201     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2202     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2203     cmp     r0, #0                      @ null array object?
   2204     beq     common_errNullObject        @ yes, bail
   2205     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2206     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2207     cmp     r1, r3                      @ compare unsigned index, length
   2208     bcs     common_errArrayIndex        @ index >= length, bail
   2209     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2210     ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
   2211     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2212     SET_VREG(r2, r9)                    @ vAA<- r2
   2213     GOTO_OPCODE(ip)                     @ jump to next instruction
   2214 
   2215 
   2216 /* ------------------------------ */
   2217     .balign 64
   2218 .L_OP_APUT: /* 0x4b */
   2219 /* File: armv5te/OP_APUT.S */
   2220     /*
   2221      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2222      *
   2223      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2224      * instructions.  We use a pair of FETCH_Bs instead.
   2225      *
   2226      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2227      */
   2228     /* op vAA, vBB, vCC */
   2229     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2230     mov     r9, rINST, lsr #8           @ r9<- AA
   2231     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2232     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2233     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2234     cmp     r0, #0                      @ null array object?
   2235     beq     common_errNullObject        @ yes, bail
   2236     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2237     add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
   2238     cmp     r1, r3                      @ compare unsigned index, length
   2239     bcs     common_errArrayIndex        @ index >= length, bail
   2240     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2241     GET_VREG(r2, r9)                    @ r2<- vAA
   2242     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2243     str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2244     GOTO_OPCODE(ip)                     @ jump to next instruction
   2245 
   2246 /* ------------------------------ */
   2247     .balign 64
   2248 .L_OP_APUT_WIDE: /* 0x4c */
   2249 /* File: armv4t/OP_APUT_WIDE.S */
   2250     /*
   2251      * Array put, 64 bits.  vBB[vCC] <- vAA.
   2252      */
   2253     /* aput-wide vAA, vBB, vCC */
   2254     FETCH(r0, 1)                        @ r0<- CCBB
   2255     mov     r9, rINST, lsr #8           @ r9<- AA
   2256     and     r2, r0, #255                @ r2<- BB
   2257     mov     r3, r0, lsr #8              @ r3<- CC
   2258     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2259     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2260     cmp     r0, #0                      @ null array object?
   2261     beq     common_errNullObject        @ yes, bail
   2262     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2263     add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
   2264     cmp     r1, r3                      @ compare unsigned index, length
   2265     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   2266     bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
   2267     b       common_errArrayIndex        @ index >= length, bail
   2268     @ May want to swap the order of these two branches depending on how the
   2269     @ branch prediction (if any) handles conditional forward branches vs.
   2270     @ unconditional forward branches.
   2271 
   2272 /* ------------------------------ */
   2273     .balign 64
   2274 .L_OP_APUT_OBJECT: /* 0x4d */
   2275 /* File: armv5te/OP_APUT_OBJECT.S */
   2276     /*
   2277      * Store an object into an array.  vBB[vCC] <- vAA.
   2278      *
   2279      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2280      * instructions.  We use a pair of FETCH_Bs instead.
   2281      */
   2282     /* op vAA, vBB, vCC */
   2283     FETCH(r0, 1)                        @ r0<- CCBB
   2284     mov     r9, rINST, lsr #8           @ r9<- AA
   2285     and     r2, r0, #255                @ r2<- BB
   2286     mov     r3, r0, lsr #8              @ r3<- CC
   2287     GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
   2288     GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
   2289     cmp     rINST, #0                   @ null array object?
   2290     GET_VREG(r9, r9)                    @ r9<- vAA
   2291     beq     common_errNullObject        @ yes, bail
   2292     ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
   2293     add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
   2294     cmp     r0, r3                      @ compare unsigned index, length
   2295     bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
   2296     b       common_errArrayIndex        @ index >= length, bail
   2297 
   2298 
   2299 /* ------------------------------ */
   2300     .balign 64
   2301 .L_OP_APUT_BOOLEAN: /* 0x4e */
   2302 /* File: armv5te/OP_APUT_BOOLEAN.S */
   2303 /* File: armv5te/OP_APUT.S */
   2304     /*
   2305      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2306      *
   2307      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2308      * instructions.  We use a pair of FETCH_Bs instead.
   2309      *
   2310      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2311      */
   2312     /* op vAA, vBB, vCC */
   2313     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2314     mov     r9, rINST, lsr #8           @ r9<- AA
   2315     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2316     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2317     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2318     cmp     r0, #0                      @ null array object?
   2319     beq     common_errNullObject        @ yes, bail
   2320     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2321     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2322     cmp     r1, r3                      @ compare unsigned index, length
   2323     bcs     common_errArrayIndex        @ index >= length, bail
   2324     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2325     GET_VREG(r2, r9)                    @ r2<- vAA
   2326     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2327     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2328     GOTO_OPCODE(ip)                     @ jump to next instruction
   2329 
   2330 
   2331 /* ------------------------------ */
   2332     .balign 64
   2333 .L_OP_APUT_BYTE: /* 0x4f */
   2334 /* File: armv5te/OP_APUT_BYTE.S */
   2335 /* File: armv5te/OP_APUT.S */
   2336     /*
   2337      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2338      *
   2339      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2340      * instructions.  We use a pair of FETCH_Bs instead.
   2341      *
   2342      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2343      */
   2344     /* op vAA, vBB, vCC */
   2345     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2346     mov     r9, rINST, lsr #8           @ r9<- AA
   2347     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2348     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2349     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2350     cmp     r0, #0                      @ null array object?
   2351     beq     common_errNullObject        @ yes, bail
   2352     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2353     add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
   2354     cmp     r1, r3                      @ compare unsigned index, length
   2355     bcs     common_errArrayIndex        @ index >= length, bail
   2356     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2357     GET_VREG(r2, r9)                    @ r2<- vAA
   2358     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2359     strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2360     GOTO_OPCODE(ip)                     @ jump to next instruction
   2361 
   2362 
   2363 /* ------------------------------ */
   2364     .balign 64
   2365 .L_OP_APUT_CHAR: /* 0x50 */
   2366 /* File: armv5te/OP_APUT_CHAR.S */
   2367 /* File: armv5te/OP_APUT.S */
   2368     /*
   2369      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2370      *
   2371      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2372      * instructions.  We use a pair of FETCH_Bs instead.
   2373      *
   2374      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2375      */
   2376     /* op vAA, vBB, vCC */
   2377     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2378     mov     r9, rINST, lsr #8           @ r9<- AA
   2379     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2380     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2381     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2382     cmp     r0, #0                      @ null array object?
   2383     beq     common_errNullObject        @ yes, bail
   2384     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2385     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2386     cmp     r1, r3                      @ compare unsigned index, length
   2387     bcs     common_errArrayIndex        @ index >= length, bail
   2388     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2389     GET_VREG(r2, r9)                    @ r2<- vAA
   2390     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2391     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2392     GOTO_OPCODE(ip)                     @ jump to next instruction
   2393 
   2394 
   2395 /* ------------------------------ */
   2396     .balign 64
   2397 .L_OP_APUT_SHORT: /* 0x51 */
   2398 /* File: armv5te/OP_APUT_SHORT.S */
   2399 /* File: armv5te/OP_APUT.S */
   2400     /*
   2401      * Array put, 32 bits or less.  vBB[vCC] <- vAA.
   2402      *
   2403      * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
   2404      * instructions.  We use a pair of FETCH_Bs instead.
   2405      *
   2406      * for: aput, aput-boolean, aput-byte, aput-char, aput-short
   2407      */
   2408     /* op vAA, vBB, vCC */
   2409     FETCH_B(r2, 1, 0)                   @ r2<- BB
   2410     mov     r9, rINST, lsr #8           @ r9<- AA
   2411     FETCH_B(r3, 1, 1)                   @ r3<- CC
   2412     GET_VREG(r0, r2)                    @ r0<- vBB (array object)
   2413     GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
   2414     cmp     r0, #0                      @ null array object?
   2415     beq     common_errNullObject        @ yes, bail
   2416     ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
   2417     add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
   2418     cmp     r1, r3                      @ compare unsigned index, length
   2419     bcs     common_errArrayIndex        @ index >= length, bail
   2420     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2421     GET_VREG(r2, r9)                    @ r2<- vAA
   2422     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2423     strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
   2424     GOTO_OPCODE(ip)                     @ jump to next instruction
   2425 
   2426 
   2427 /* ------------------------------ */
   2428     .balign 64
   2429 .L_OP_IGET: /* 0x52 */
   2430 /* File: armv5te/OP_IGET.S */
   2431     /*
   2432      * General 32-bit instance field get.
   2433      *
   2434      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2435      */
   2436     /* op vA, vB, field@CCCC */
   2437     mov     r0, rINST, lsr #12          @ r0<- B
   2438     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2439     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2440     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2441     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2442     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2443     cmp     r0, #0                      @ is resolved entry null?
   2444     bne     .LOP_IGET_finish          @ no, already resolved
   2445 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2446     EXPORT_PC()                         @ resolve() could throw
   2447     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2448     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2449     cmp     r0, #0
   2450     bne     .LOP_IGET_finish
   2451     b       common_exceptionThrown
   2452 
   2453 /* ------------------------------ */
   2454     .balign 64
   2455 .L_OP_IGET_WIDE: /* 0x53 */
   2456 /* File: armv4t/OP_IGET_WIDE.S */
   2457     /*
   2458      * Wide 32-bit instance field get.
   2459      */
   2460     /* iget-wide vA, vB, field@CCCC */
   2461     mov     r0, rINST, lsr #12          @ r0<- B
   2462     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2463     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2464     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   2465     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2466     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2467     cmp     r0, #0                      @ is resolved entry null?
   2468     bne     .LOP_IGET_WIDE_finish          @ no, already resolved
   2469 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   2470     EXPORT_PC()                         @ resolve() could throw
   2471     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2472     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2473     cmp     r0, #0
   2474     bne     .LOP_IGET_WIDE_finish
   2475     b       common_exceptionThrown
   2476 
   2477 /* ------------------------------ */
   2478     .balign 64
   2479 .L_OP_IGET_OBJECT: /* 0x54 */
   2480 /* File: armv5te/OP_IGET_OBJECT.S */
   2481 /* File: armv5te/OP_IGET.S */
   2482     /*
   2483      * General 32-bit instance field get.
   2484      *
   2485      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2486      */
   2487     /* op vA, vB, field@CCCC */
   2488     mov     r0, rINST, lsr #12          @ r0<- B
   2489     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2490     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2491     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2492     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2493     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2494     cmp     r0, #0                      @ is resolved entry null?
   2495     bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
   2496 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2497     EXPORT_PC()                         @ resolve() could throw
   2498     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2499     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2500     cmp     r0, #0
   2501     bne     .LOP_IGET_OBJECT_finish
   2502     b       common_exceptionThrown
   2503 
   2504 
   2505 /* ------------------------------ */
   2506     .balign 64
   2507 .L_OP_IGET_BOOLEAN: /* 0x55 */
   2508 /* File: armv5te/OP_IGET_BOOLEAN.S */
   2509 @include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
   2510 /* File: armv5te/OP_IGET.S */
   2511     /*
   2512      * General 32-bit instance field get.
   2513      *
   2514      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2515      */
   2516     /* op vA, vB, field@CCCC */
   2517     mov     r0, rINST, lsr #12          @ r0<- B
   2518     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2519     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2520     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2521     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2522     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2523     cmp     r0, #0                      @ is resolved entry null?
   2524     bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
   2525 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2526     EXPORT_PC()                         @ resolve() could throw
   2527     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2528     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2529     cmp     r0, #0
   2530     bne     .LOP_IGET_BOOLEAN_finish
   2531     b       common_exceptionThrown
   2532 
   2533 
   2534 /* ------------------------------ */
   2535     .balign 64
   2536 .L_OP_IGET_BYTE: /* 0x56 */
   2537 /* File: armv5te/OP_IGET_BYTE.S */
   2538 @include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
   2539 /* File: armv5te/OP_IGET.S */
   2540     /*
   2541      * General 32-bit instance field get.
   2542      *
   2543      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2544      */
   2545     /* op vA, vB, field@CCCC */
   2546     mov     r0, rINST, lsr #12          @ r0<- B
   2547     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2548     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2549     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2550     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2551     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2552     cmp     r0, #0                      @ is resolved entry null?
   2553     bne     .LOP_IGET_BYTE_finish          @ no, already resolved
   2554 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2555     EXPORT_PC()                         @ resolve() could throw
   2556     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2557     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2558     cmp     r0, #0
   2559     bne     .LOP_IGET_BYTE_finish
   2560     b       common_exceptionThrown
   2561 
   2562 
   2563 /* ------------------------------ */
   2564     .balign 64
   2565 .L_OP_IGET_CHAR: /* 0x57 */
   2566 /* File: armv5te/OP_IGET_CHAR.S */
   2567 @include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
   2568 /* File: armv5te/OP_IGET.S */
   2569     /*
   2570      * General 32-bit instance field get.
   2571      *
   2572      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2573      */
   2574     /* op vA, vB, field@CCCC */
   2575     mov     r0, rINST, lsr #12          @ r0<- B
   2576     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2577     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2578     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2579     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2580     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2581     cmp     r0, #0                      @ is resolved entry null?
   2582     bne     .LOP_IGET_CHAR_finish          @ no, already resolved
   2583 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2584     EXPORT_PC()                         @ resolve() could throw
   2585     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2586     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2587     cmp     r0, #0
   2588     bne     .LOP_IGET_CHAR_finish
   2589     b       common_exceptionThrown
   2590 
   2591 
   2592 /* ------------------------------ */
   2593     .balign 64
   2594 .L_OP_IGET_SHORT: /* 0x58 */
   2595 /* File: armv5te/OP_IGET_SHORT.S */
   2596 @include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
   2597 /* File: armv5te/OP_IGET.S */
   2598     /*
   2599      * General 32-bit instance field get.
   2600      *
   2601      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   2602      */
   2603     /* op vA, vB, field@CCCC */
   2604     mov     r0, rINST, lsr #12          @ r0<- B
   2605     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2606     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2607     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2608     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2609     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2610     cmp     r0, #0                      @ is resolved entry null?
   2611     bne     .LOP_IGET_SHORT_finish          @ no, already resolved
   2612 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2613     EXPORT_PC()                         @ resolve() could throw
   2614     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2615     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2616     cmp     r0, #0
   2617     bne     .LOP_IGET_SHORT_finish
   2618     b       common_exceptionThrown
   2619 
   2620 
   2621 /* ------------------------------ */
   2622     .balign 64
   2623 .L_OP_IPUT: /* 0x59 */
   2624 /* File: armv5te/OP_IPUT.S */
   2625     /*
   2626      * General 32-bit instance field put.
   2627      *
   2628      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2629      */
   2630     /* op vA, vB, field@CCCC */
   2631     mov     r0, rINST, lsr #12          @ r0<- B
   2632     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2633     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2634     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2635     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2636     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2637     cmp     r0, #0                      @ is resolved entry null?
   2638     bne     .LOP_IPUT_finish          @ no, already resolved
   2639 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2640     EXPORT_PC()                         @ resolve() could throw
   2641     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2642     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2643     cmp     r0, #0                      @ success?
   2644     bne     .LOP_IPUT_finish          @ yes, finish up
   2645     b       common_exceptionThrown
   2646 
   2647 /* ------------------------------ */
   2648     .balign 64
   2649 .L_OP_IPUT_WIDE: /* 0x5a */
   2650 /* File: armv4t/OP_IPUT_WIDE.S */
   2651     /* iput-wide vA, vB, field@CCCC */
   2652     mov     r0, rINST, lsr #12          @ r0<- B
   2653     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2654     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2655     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   2656     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2657     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2658     cmp     r0, #0                      @ is resolved entry null?
   2659     bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
   2660 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   2661     EXPORT_PC()                         @ resolve() could throw
   2662     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2663     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2664     cmp     r0, #0                      @ success?
   2665     bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
   2666     b       common_exceptionThrown
   2667 
   2668 /* ------------------------------ */
   2669     .balign 64
   2670 .L_OP_IPUT_OBJECT: /* 0x5b */
   2671 /* File: armv5te/OP_IPUT_OBJECT.S */
   2672     /*
   2673      * 32-bit instance field put.
   2674      *
   2675      * for: iput-object, iput-object-volatile
   2676      */
   2677     /* op vA, vB, field@CCCC */
   2678     mov     r0, rINST, lsr #12          @ r0<- B
   2679     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2680     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2681     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2682     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2683     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2684     cmp     r0, #0                      @ is resolved entry null?
   2685     bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
   2686 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2687     EXPORT_PC()                         @ resolve() could throw
   2688     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2689     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2690     cmp     r0, #0                      @ success?
   2691     bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
   2692     b       common_exceptionThrown
   2693 
   2694 /* ------------------------------ */
   2695     .balign 64
   2696 .L_OP_IPUT_BOOLEAN: /* 0x5c */
   2697 /* File: armv5te/OP_IPUT_BOOLEAN.S */
   2698 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
   2699 /* File: armv5te/OP_IPUT.S */
   2700     /*
   2701      * General 32-bit instance field put.
   2702      *
   2703      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2704      */
   2705     /* op vA, vB, field@CCCC */
   2706     mov     r0, rINST, lsr #12          @ r0<- B
   2707     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2708     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2709     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2710     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2711     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2712     cmp     r0, #0                      @ is resolved entry null?
   2713     bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
   2714 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2715     EXPORT_PC()                         @ resolve() could throw
   2716     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2717     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2718     cmp     r0, #0                      @ success?
   2719     bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
   2720     b       common_exceptionThrown
   2721 
   2722 
   2723 /* ------------------------------ */
   2724     .balign 64
   2725 .L_OP_IPUT_BYTE: /* 0x5d */
   2726 /* File: armv5te/OP_IPUT_BYTE.S */
   2727 @include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
   2728 /* File: armv5te/OP_IPUT.S */
   2729     /*
   2730      * General 32-bit instance field put.
   2731      *
   2732      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2733      */
   2734     /* op vA, vB, field@CCCC */
   2735     mov     r0, rINST, lsr #12          @ r0<- B
   2736     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2737     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2738     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2739     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2740     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2741     cmp     r0, #0                      @ is resolved entry null?
   2742     bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
   2743 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2744     EXPORT_PC()                         @ resolve() could throw
   2745     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2746     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2747     cmp     r0, #0                      @ success?
   2748     bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
   2749     b       common_exceptionThrown
   2750 
   2751 
   2752 /* ------------------------------ */
   2753     .balign 64
   2754 .L_OP_IPUT_CHAR: /* 0x5e */
   2755 /* File: armv5te/OP_IPUT_CHAR.S */
   2756 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
   2757 /* File: armv5te/OP_IPUT.S */
   2758     /*
   2759      * General 32-bit instance field put.
   2760      *
   2761      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2762      */
   2763     /* op vA, vB, field@CCCC */
   2764     mov     r0, rINST, lsr #12          @ r0<- B
   2765     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2766     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2767     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2768     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2769     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2770     cmp     r0, #0                      @ is resolved entry null?
   2771     bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
   2772 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2773     EXPORT_PC()                         @ resolve() could throw
   2774     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2775     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2776     cmp     r0, #0                      @ success?
   2777     bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
   2778     b       common_exceptionThrown
   2779 
   2780 
   2781 /* ------------------------------ */
   2782     .balign 64
   2783 .L_OP_IPUT_SHORT: /* 0x5f */
   2784 /* File: armv5te/OP_IPUT_SHORT.S */
   2785 @include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
   2786 /* File: armv5te/OP_IPUT.S */
   2787     /*
   2788      * General 32-bit instance field put.
   2789      *
   2790      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   2791      */
   2792     /* op vA, vB, field@CCCC */
   2793     mov     r0, rINST, lsr #12          @ r0<- B
   2794     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   2795     FETCH(r1, 1)                        @ r1<- field ref CCCC
   2796     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   2797     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   2798     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   2799     cmp     r0, #0                      @ is resolved entry null?
   2800     bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
   2801 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   2802     EXPORT_PC()                         @ resolve() could throw
   2803     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   2804     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   2805     cmp     r0, #0                      @ success?
   2806     bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
   2807     b       common_exceptionThrown
   2808 
   2809 
   2810 /* ------------------------------ */
   2811     .balign 64
   2812 .L_OP_SGET: /* 0x60 */
   2813 /* File: armv5te/OP_SGET.S */
   2814     /*
   2815      * General 32-bit SGET handler.
   2816      *
   2817      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2818      */
   2819     /* op vAA, field@BBBB */
   2820     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2821     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2822     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2823     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2824     cmp     r0, #0                      @ is resolved entry null?
   2825     beq     .LOP_SGET_resolve         @ yes, do resolve
   2826 .LOP_SGET_finish: @ field ptr in r0
   2827     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2828     @ no-op                             @ acquiring load
   2829     mov     r2, rINST, lsr #8           @ r2<- AA
   2830     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2831     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2832     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2833     GOTO_OPCODE(ip)                     @ jump to next instruction
   2834 
   2835 /* ------------------------------ */
   2836     .balign 64
   2837 .L_OP_SGET_WIDE: /* 0x61 */
   2838 /* File: armv4t/OP_SGET_WIDE.S */
   2839     /*
   2840      * 64-bit SGET handler.
   2841      */
   2842     /* sget-wide vAA, field@BBBB */
   2843     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2844     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2845     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2846     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2847     cmp     r0, #0                      @ is resolved entry null?
   2848     beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
   2849 .LOP_SGET_WIDE_finish:
   2850     mov     r9, rINST, lsr #8           @ r9<- AA
   2851     add     r0, r0, #offStaticField_value @ r0<- pointer to data
   2852     .if 0
   2853     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   2854     .else
   2855     ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
   2856     .endif
   2857     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   2858     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2859     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   2860     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2861     GOTO_OPCODE(ip)                     @ jump to next instruction
   2862 
   2863 /* ------------------------------ */
   2864     .balign 64
   2865 .L_OP_SGET_OBJECT: /* 0x62 */
   2866 /* File: armv5te/OP_SGET_OBJECT.S */
   2867 /* File: armv5te/OP_SGET.S */
   2868     /*
   2869      * General 32-bit SGET handler.
   2870      *
   2871      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2872      */
   2873     /* op vAA, field@BBBB */
   2874     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2875     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2876     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2877     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2878     cmp     r0, #0                      @ is resolved entry null?
   2879     beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
   2880 .LOP_SGET_OBJECT_finish: @ field ptr in r0
   2881     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2882     @ no-op                             @ acquiring load
   2883     mov     r2, rINST, lsr #8           @ r2<- AA
   2884     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2885     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2886     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2887     GOTO_OPCODE(ip)                     @ jump to next instruction
   2888 
   2889 
   2890 /* ------------------------------ */
   2891     .balign 64
   2892 .L_OP_SGET_BOOLEAN: /* 0x63 */
   2893 /* File: armv5te/OP_SGET_BOOLEAN.S */
   2894 /* File: armv5te/OP_SGET.S */
   2895     /*
   2896      * General 32-bit SGET handler.
   2897      *
   2898      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2899      */
   2900     /* op vAA, field@BBBB */
   2901     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2902     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2903     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2904     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2905     cmp     r0, #0                      @ is resolved entry null?
   2906     beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
   2907 .LOP_SGET_BOOLEAN_finish: @ field ptr in r0
   2908     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2909     @ no-op                             @ acquiring load
   2910     mov     r2, rINST, lsr #8           @ r2<- AA
   2911     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2912     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2913     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2914     GOTO_OPCODE(ip)                     @ jump to next instruction
   2915 
   2916 
   2917 /* ------------------------------ */
   2918     .balign 64
   2919 .L_OP_SGET_BYTE: /* 0x64 */
   2920 /* File: armv5te/OP_SGET_BYTE.S */
   2921 /* File: armv5te/OP_SGET.S */
   2922     /*
   2923      * General 32-bit SGET handler.
   2924      *
   2925      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2926      */
   2927     /* op vAA, field@BBBB */
   2928     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2929     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2930     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2931     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2932     cmp     r0, #0                      @ is resolved entry null?
   2933     beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
   2934 .LOP_SGET_BYTE_finish: @ field ptr in r0
   2935     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2936     @ no-op                             @ acquiring load
   2937     mov     r2, rINST, lsr #8           @ r2<- AA
   2938     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2939     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2940     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2941     GOTO_OPCODE(ip)                     @ jump to next instruction
   2942 
   2943 
   2944 /* ------------------------------ */
   2945     .balign 64
   2946 .L_OP_SGET_CHAR: /* 0x65 */
   2947 /* File: armv5te/OP_SGET_CHAR.S */
   2948 /* File: armv5te/OP_SGET.S */
   2949     /*
   2950      * General 32-bit SGET handler.
   2951      *
   2952      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2953      */
   2954     /* op vAA, field@BBBB */
   2955     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2956     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2957     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2958     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2959     cmp     r0, #0                      @ is resolved entry null?
   2960     beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
   2961 .LOP_SGET_CHAR_finish: @ field ptr in r0
   2962     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2963     @ no-op                             @ acquiring load
   2964     mov     r2, rINST, lsr #8           @ r2<- AA
   2965     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2966     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2967     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2968     GOTO_OPCODE(ip)                     @ jump to next instruction
   2969 
   2970 
   2971 /* ------------------------------ */
   2972     .balign 64
   2973 .L_OP_SGET_SHORT: /* 0x66 */
   2974 /* File: armv5te/OP_SGET_SHORT.S */
   2975 /* File: armv5te/OP_SGET.S */
   2976     /*
   2977      * General 32-bit SGET handler.
   2978      *
   2979      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   2980      */
   2981     /* op vAA, field@BBBB */
   2982     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   2983     FETCH(r1, 1)                        @ r1<- field ref BBBB
   2984     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   2985     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   2986     cmp     r0, #0                      @ is resolved entry null?
   2987     beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
   2988 .LOP_SGET_SHORT_finish: @ field ptr in r0
   2989     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   2990     @ no-op                             @ acquiring load
   2991     mov     r2, rINST, lsr #8           @ r2<- AA
   2992     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   2993     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   2994     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   2995     GOTO_OPCODE(ip)                     @ jump to next instruction
   2996 
   2997 
   2998 /* ------------------------------ */
   2999     .balign 64
   3000 .L_OP_SPUT: /* 0x67 */
   3001 /* File: armv5te/OP_SPUT.S */
   3002     /*
   3003      * General 32-bit SPUT handler.
   3004      *
   3005      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3006      */
   3007     /* op vAA, field@BBBB */
   3008     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3009     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3010     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3011     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3012     cmp     r0, #0                      @ is resolved entry null?
   3013     beq     .LOP_SPUT_resolve         @ yes, do resolve
   3014 .LOP_SPUT_finish:   @ field ptr in r0
   3015     mov     r2, rINST, lsr #8           @ r2<- AA
   3016     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3017     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3018     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3019     @ no-op                             @ releasing store
   3020     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3021     GOTO_OPCODE(ip)                     @ jump to next instruction
   3022 
   3023 /* ------------------------------ */
   3024     .balign 64
   3025 .L_OP_SPUT_WIDE: /* 0x68 */
   3026 /* File: armv4t/OP_SPUT_WIDE.S */
   3027     /*
   3028      * 64-bit SPUT handler.
   3029      */
   3030     /* sput-wide vAA, field@BBBB */
   3031     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
   3032     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3033     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
   3034     mov     r9, rINST, lsr #8           @ r9<- AA
   3035     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
   3036     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   3037     cmp     r2, #0                      @ is resolved entry null?
   3038     beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
   3039 .LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
   3040     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3041     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   3042     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   3043     add     r2, r2, #offStaticField_value @ r2<- pointer to data
   3044     .if 0
   3045     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   3046     .else
   3047     stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
   3048     .endif
   3049     GOTO_OPCODE(r10)                    @ jump to next instruction
   3050 
   3051 /* ------------------------------ */
   3052     .balign 64
   3053 .L_OP_SPUT_OBJECT: /* 0x69 */
   3054 /* File: armv5te/OP_SPUT_OBJECT.S */
   3055     /*
   3056      * 32-bit SPUT handler for objects
   3057      *
   3058      * for: sput-object, sput-object-volatile
   3059      */
   3060     /* op vAA, field@BBBB */
   3061     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3062     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3063     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3064     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3065     cmp     r0, #0                      @ is resolved entry null?
   3066     bne     .LOP_SPUT_OBJECT_finish          @ no, continue
   3067     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
   3068     EXPORT_PC()                         @ resolve() could throw, so export now
   3069     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
   3070     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   3071     cmp     r0, #0                      @ success?
   3072     bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
   3073     b       common_exceptionThrown      @ no, handle exception
   3074 
   3075 
   3076 /* ------------------------------ */
   3077     .balign 64
   3078 .L_OP_SPUT_BOOLEAN: /* 0x6a */
   3079 /* File: armv5te/OP_SPUT_BOOLEAN.S */
   3080 /* File: armv5te/OP_SPUT.S */
   3081     /*
   3082      * General 32-bit SPUT handler.
   3083      *
   3084      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3085      */
   3086     /* op vAA, field@BBBB */
   3087     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3088     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3089     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3090     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3091     cmp     r0, #0                      @ is resolved entry null?
   3092     beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
   3093 .LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
   3094     mov     r2, rINST, lsr #8           @ r2<- AA
   3095     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3096     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3097     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3098     @ no-op                             @ releasing store
   3099     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3100     GOTO_OPCODE(ip)                     @ jump to next instruction
   3101 
   3102 
   3103 /* ------------------------------ */
   3104     .balign 64
   3105 .L_OP_SPUT_BYTE: /* 0x6b */
   3106 /* File: armv5te/OP_SPUT_BYTE.S */
   3107 /* File: armv5te/OP_SPUT.S */
   3108     /*
   3109      * General 32-bit SPUT handler.
   3110      *
   3111      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3112      */
   3113     /* op vAA, field@BBBB */
   3114     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3115     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3116     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3117     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3118     cmp     r0, #0                      @ is resolved entry null?
   3119     beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
   3120 .LOP_SPUT_BYTE_finish:   @ field ptr in r0
   3121     mov     r2, rINST, lsr #8           @ r2<- AA
   3122     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3123     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3124     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3125     @ no-op                             @ releasing store
   3126     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3127     GOTO_OPCODE(ip)                     @ jump to next instruction
   3128 
   3129 
   3130 /* ------------------------------ */
   3131     .balign 64
   3132 .L_OP_SPUT_CHAR: /* 0x6c */
   3133 /* File: armv5te/OP_SPUT_CHAR.S */
   3134 /* File: armv5te/OP_SPUT.S */
   3135     /*
   3136      * General 32-bit SPUT handler.
   3137      *
   3138      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3139      */
   3140     /* op vAA, field@BBBB */
   3141     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3142     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3143     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3144     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3145     cmp     r0, #0                      @ is resolved entry null?
   3146     beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
   3147 .LOP_SPUT_CHAR_finish:   @ field ptr in r0
   3148     mov     r2, rINST, lsr #8           @ r2<- AA
   3149     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3150     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3151     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3152     @ no-op                             @ releasing store
   3153     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3154     GOTO_OPCODE(ip)                     @ jump to next instruction
   3155 
   3156 
   3157 /* ------------------------------ */
   3158     .balign 64
   3159 .L_OP_SPUT_SHORT: /* 0x6d */
   3160 /* File: armv5te/OP_SPUT_SHORT.S */
   3161 /* File: armv5te/OP_SPUT.S */
   3162     /*
   3163      * General 32-bit SPUT handler.
   3164      *
   3165      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   3166      */
   3167     /* op vAA, field@BBBB */
   3168     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   3169     FETCH(r1, 1)                        @ r1<- field ref BBBB
   3170     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   3171     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   3172     cmp     r0, #0                      @ is resolved entry null?
   3173     beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
   3174 .LOP_SPUT_SHORT_finish:   @ field ptr in r0
   3175     mov     r2, rINST, lsr #8           @ r2<- AA
   3176     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   3177     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   3178     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3179     @ no-op                             @ releasing store
   3180     str     r1, [r0, #offStaticField_value] @ field<- vAA
   3181     GOTO_OPCODE(ip)                     @ jump to next instruction
   3182 
   3183 
   3184 /* ------------------------------ */
   3185     .balign 64
   3186 .L_OP_INVOKE_VIRTUAL: /* 0x6e */
   3187 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
   3188     /*
   3189      * Handle a virtual method call.
   3190      *
   3191      * for: invoke-virtual, invoke-virtual/range
   3192      */
   3193     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3194     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3195     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3196     FETCH(r1, 1)                        @ r1<- BBBB
   3197     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3198     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3199     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3200     .if     (!0)
   3201     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3202     .endif
   3203     cmp     r0, #0                      @ already resolved?
   3204     EXPORT_PC()                         @ must export for invoke
   3205     bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
   3206     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3207     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3208     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   3209     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3210     cmp     r0, #0                      @ got null?
   3211     bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
   3212     b       common_exceptionThrown      @ yes, handle exception
   3213 
   3214 /* ------------------------------ */
   3215     .balign 64
   3216 .L_OP_INVOKE_SUPER: /* 0x6f */
   3217 /* File: armv5te/OP_INVOKE_SUPER.S */
   3218     /*
   3219      * Handle a "super" method call.
   3220      *
   3221      * for: invoke-super, invoke-super/range
   3222      */
   3223     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3224     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3225     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3226     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3227     .if     (!0)
   3228     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3229     .endif
   3230     FETCH(r1, 1)                        @ r1<- BBBB
   3231     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3232     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3233     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3234     cmp     r2, #0                      @ null "this"?
   3235     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
   3236     beq     common_errNullObject        @ null "this", throw exception
   3237     cmp     r0, #0                      @ already resolved?
   3238     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
   3239     EXPORT_PC()                         @ must export for invoke
   3240     bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
   3241     b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
   3242 
   3243 /* ------------------------------ */
   3244     .balign 64
   3245 .L_OP_INVOKE_DIRECT: /* 0x70 */
   3246 /* File: armv5te/OP_INVOKE_DIRECT.S */
   3247     /*
   3248      * Handle a direct method call.
   3249      *
   3250      * (We could defer the "is 'this' pointer null" test to the common
   3251      * method invocation code, and use a flag to indicate that static
   3252      * calls don't count.  If we do this as part of copying the arguments
   3253      * out we could avoiding loading the first arg twice.)
   3254      *
   3255      * for: invoke-direct, invoke-direct/range
   3256      */
   3257     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3258     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3259     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3260     FETCH(r1, 1)                        @ r1<- BBBB
   3261     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3262     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3263     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3264     .if     (!0)
   3265     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3266     .endif
   3267     cmp     r0, #0                      @ already resolved?
   3268     EXPORT_PC()                         @ must export for invoke
   3269     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3270     beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
   3271 .LOP_INVOKE_DIRECT_finish:
   3272     cmp     r2, #0                      @ null "this" ref?
   3273     bne     common_invokeMethodNoRange   @ no, continue on
   3274     b       common_errNullObject        @ yes, throw exception
   3275 
   3276 /* ------------------------------ */
   3277     .balign 64
   3278 .L_OP_INVOKE_STATIC: /* 0x71 */
   3279 /* File: armv5te/OP_INVOKE_STATIC.S */
   3280     /*
   3281      * Handle a static method call.
   3282      *
   3283      * for: invoke-static, invoke-static/range
   3284      */
   3285     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3286     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3287     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3288     FETCH(r1, 1)                        @ r1<- BBBB
   3289     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3290     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3291     cmp     r0, #0                      @ already resolved?
   3292     EXPORT_PC()                         @ must export for invoke
   3293     bne     common_invokeMethodNoRange @ yes, continue on
   3294 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3295     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3296     mov     r2, #METHOD_STATIC          @ resolver method type
   3297     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3298     cmp     r0, #0                      @ got null?
   3299     bne     common_invokeMethodNoRange @ no, continue
   3300     b       common_exceptionThrown      @ yes, handle exception
   3301 
   3302 /* ------------------------------ */
   3303     .balign 64
   3304 .L_OP_INVOKE_INTERFACE: /* 0x72 */
   3305 /* File: armv5te/OP_INVOKE_INTERFACE.S */
   3306     /*
   3307      * Handle an interface method call.
   3308      *
   3309      * for: invoke-interface, invoke-interface/range
   3310      */
   3311     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3312     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3313     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
   3314     FETCH(r1, 1)                        @ r1<- BBBB
   3315     .if     (!0)
   3316     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
   3317     .endif
   3318     EXPORT_PC()                         @ must export for invoke
   3319     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
   3320     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
   3321     cmp     r0, #0                      @ null obj?
   3322     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
   3323     beq     common_errNullObject        @ yes, fail
   3324     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
   3325     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
   3326     cmp     r0, #0                      @ failed?
   3327     beq     common_exceptionThrown      @ yes, handle exception
   3328     b       common_invokeMethodNoRange @ jump to common handler
   3329 
   3330 /* ------------------------------ */
   3331     .balign 64
   3332 .L_OP_UNUSED_73: /* 0x73 */
   3333 /* File: armv5te/OP_UNUSED_73.S */
   3334 /* File: armv5te/unused.S */
   3335     bl      common_abort
   3336 
   3337 
   3338 /* ------------------------------ */
   3339     .balign 64
   3340 .L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
   3341 /* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
   3342 /* File: armv5te/OP_INVOKE_VIRTUAL.S */
   3343     /*
   3344      * Handle a virtual method call.
   3345      *
   3346      * for: invoke-virtual, invoke-virtual/range
   3347      */
   3348     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3349     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3350     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3351     FETCH(r1, 1)                        @ r1<- BBBB
   3352     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3353     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3354     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3355     .if     (!1)
   3356     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3357     .endif
   3358     cmp     r0, #0                      @ already resolved?
   3359     EXPORT_PC()                         @ must export for invoke
   3360     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
   3361     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3362     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3363     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   3364     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3365     cmp     r0, #0                      @ got null?
   3366     bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
   3367     b       common_exceptionThrown      @ yes, handle exception
   3368 
   3369 
   3370 /* ------------------------------ */
   3371     .balign 64
   3372 .L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
   3373 /* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
   3374 /* File: armv5te/OP_INVOKE_SUPER.S */
   3375     /*
   3376      * Handle a "super" method call.
   3377      *
   3378      * for: invoke-super, invoke-super/range
   3379      */
   3380     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3381     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3382     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3383     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3384     .if     (!1)
   3385     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3386     .endif
   3387     FETCH(r1, 1)                        @ r1<- BBBB
   3388     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3389     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3390     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
   3391     cmp     r2, #0                      @ null "this"?
   3392     ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
   3393     beq     common_errNullObject        @ null "this", throw exception
   3394     cmp     r0, #0                      @ already resolved?
   3395     ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
   3396     EXPORT_PC()                         @ must export for invoke
   3397     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
   3398     b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
   3399 
   3400 
   3401 /* ------------------------------ */
   3402     .balign 64
   3403 .L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
   3404 /* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
   3405 /* File: armv5te/OP_INVOKE_DIRECT.S */
   3406     /*
   3407      * Handle a direct method call.
   3408      *
   3409      * (We could defer the "is 'this' pointer null" test to the common
   3410      * method invocation code, and use a flag to indicate that static
   3411      * calls don't count.  If we do this as part of copying the arguments
   3412      * out we could avoiding loading the first arg twice.)
   3413      *
   3414      * for: invoke-direct, invoke-direct/range
   3415      */
   3416     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3417     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3418     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3419     FETCH(r1, 1)                        @ r1<- BBBB
   3420     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3421     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   3422     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3423     .if     (!1)
   3424     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   3425     .endif
   3426     cmp     r0, #0                      @ already resolved?
   3427     EXPORT_PC()                         @ must export for invoke
   3428     GET_VREG(r2, r10)                   @ r2<- "this" ptr
   3429     beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
   3430 .LOP_INVOKE_DIRECT_RANGE_finish:
   3431     cmp     r2, #0                      @ null "this" ref?
   3432     bne     common_invokeMethodRange   @ no, continue on
   3433     b       common_errNullObject        @ yes, throw exception
   3434 
   3435 
   3436 /* ------------------------------ */
   3437     .balign 64
   3438 .L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
   3439 /* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
   3440 /* File: armv5te/OP_INVOKE_STATIC.S */
   3441     /*
   3442      * Handle a static method call.
   3443      *
   3444      * for: invoke-static, invoke-static/range
   3445      */
   3446     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3447     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3448     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
   3449     FETCH(r1, 1)                        @ r1<- BBBB
   3450     ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
   3451     ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
   3452     cmp     r0, #0                      @ already resolved?
   3453     EXPORT_PC()                         @ must export for invoke
   3454     bne     common_invokeMethodRange @ yes, continue on
   3455 0:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   3456     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   3457     mov     r2, #METHOD_STATIC          @ resolver method type
   3458     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   3459     cmp     r0, #0                      @ got null?
   3460     bne     common_invokeMethodRange @ no, continue
   3461     b       common_exceptionThrown      @ yes, handle exception
   3462 
   3463 
   3464 /* ------------------------------ */
   3465     .balign 64
   3466 .L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
   3467 /* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
   3468 /* File: armv5te/OP_INVOKE_INTERFACE.S */
   3469     /*
   3470      * Handle an interface method call.
   3471      *
   3472      * for: invoke-interface, invoke-interface/range
   3473      */
   3474     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   3475     /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   3476     FETCH(r2, 2)                        @ r2<- FEDC or CCCC
   3477     FETCH(r1, 1)                        @ r1<- BBBB
   3478     .if     (!1)
   3479     and     r2, r2, #15                 @ r2<- C (or stays CCCC)
   3480     .endif
   3481     EXPORT_PC()                         @ must export for invoke
   3482     GET_VREG(r0, r2)                    @ r0<- first arg ("this")
   3483     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
   3484     cmp     r0, #0                      @ null obj?
   3485     ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
   3486     beq     common_errNullObject        @ yes, fail
   3487     ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
   3488     bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
   3489     cmp     r0, #0                      @ failed?
   3490     beq     common_exceptionThrown      @ yes, handle exception
   3491     b       common_invokeMethodRange @ jump to common handler
   3492 
   3493 
   3494 /* ------------------------------ */
   3495     .balign 64
   3496 .L_OP_UNUSED_79: /* 0x79 */
   3497 /* File: armv5te/OP_UNUSED_79.S */
   3498 /* File: armv5te/unused.S */
   3499     bl      common_abort
   3500 
   3501 
   3502 /* ------------------------------ */
   3503     .balign 64
   3504 .L_OP_UNUSED_7A: /* 0x7a */
   3505 /* File: armv5te/OP_UNUSED_7A.S */
   3506 /* File: armv5te/unused.S */
   3507     bl      common_abort
   3508 
   3509 
   3510 /* ------------------------------ */
   3511     .balign 64
   3512 .L_OP_NEG_INT: /* 0x7b */
   3513 /* File: armv5te/OP_NEG_INT.S */
   3514 /* File: armv5te/unop.S */
   3515     /*
   3516      * Generic 32-bit unary operation.  Provide an "instr" line that
   3517      * specifies an instruction that performs "result = op r0".
   3518      * This could be an ARM instruction or a function call.
   3519      *
   3520      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3521      *      int-to-byte, int-to-char, int-to-short
   3522      */
   3523     /* unop vA, vB */
   3524     mov     r3, rINST, lsr #12          @ r3<- B
   3525     mov     r9, rINST, lsr #8           @ r9<- A+
   3526     GET_VREG(r0, r3)                    @ r0<- vB
   3527     and     r9, r9, #15
   3528                                @ optional op; may set condition codes
   3529     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3530     rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
   3531     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3532     SET_VREG(r0, r9)                    @ vAA<- r0
   3533     GOTO_OPCODE(ip)                     @ jump to next instruction
   3534     /* 9-10 instructions */
   3535 
   3536 
   3537 /* ------------------------------ */
   3538     .balign 64
   3539 .L_OP_NOT_INT: /* 0x7c */
   3540 /* File: armv5te/OP_NOT_INT.S */
   3541 /* File: armv5te/unop.S */
   3542     /*
   3543      * Generic 32-bit unary operation.  Provide an "instr" line that
   3544      * specifies an instruction that performs "result = op r0".
   3545      * This could be an ARM instruction or a function call.
   3546      *
   3547      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3548      *      int-to-byte, int-to-char, int-to-short
   3549      */
   3550     /* unop vA, vB */
   3551     mov     r3, rINST, lsr #12          @ r3<- B
   3552     mov     r9, rINST, lsr #8           @ r9<- A+
   3553     GET_VREG(r0, r3)                    @ r0<- vB
   3554     and     r9, r9, #15
   3555                                @ optional op; may set condition codes
   3556     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3557     mvn     r0, r0                              @ r0<- op, r0-r3 changed
   3558     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3559     SET_VREG(r0, r9)                    @ vAA<- r0
   3560     GOTO_OPCODE(ip)                     @ jump to next instruction
   3561     /* 9-10 instructions */
   3562 
   3563 
   3564 /* ------------------------------ */
   3565     .balign 64
   3566 .L_OP_NEG_LONG: /* 0x7d */
   3567 /* File: armv5te/OP_NEG_LONG.S */
   3568 /* File: armv5te/unopWide.S */
   3569     /*
   3570      * Generic 64-bit unary operation.  Provide an "instr" line that
   3571      * specifies an instruction that performs "result = op r0/r1".
   3572      * This could be an ARM instruction or a function call.
   3573      *
   3574      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3575      */
   3576     /* unop vA, vB */
   3577     mov     r9, rINST, lsr #8           @ r9<- A+
   3578     mov     r3, rINST, lsr #12          @ r3<- B
   3579     and     r9, r9, #15
   3580     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3581     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3582     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3583     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3584     rsbs    r0, r0, #0                           @ optional op; may set condition codes
   3585     rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
   3586     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3587     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3588     GOTO_OPCODE(ip)                     @ jump to next instruction
   3589     /* 12-13 instructions */
   3590 
   3591 
   3592 /* ------------------------------ */
   3593     .balign 64
   3594 .L_OP_NOT_LONG: /* 0x7e */
   3595 /* File: armv5te/OP_NOT_LONG.S */
   3596 /* File: armv5te/unopWide.S */
   3597     /*
   3598      * Generic 64-bit unary operation.  Provide an "instr" line that
   3599      * specifies an instruction that performs "result = op r0/r1".
   3600      * This could be an ARM instruction or a function call.
   3601      *
   3602      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3603      */
   3604     /* unop vA, vB */
   3605     mov     r9, rINST, lsr #8           @ r9<- A+
   3606     mov     r3, rINST, lsr #12          @ r3<- B
   3607     and     r9, r9, #15
   3608     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3609     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3610     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3611     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3612     mvn     r0, r0                           @ optional op; may set condition codes
   3613     mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
   3614     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3615     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3616     GOTO_OPCODE(ip)                     @ jump to next instruction
   3617     /* 12-13 instructions */
   3618 
   3619 
   3620 /* ------------------------------ */
   3621     .balign 64
   3622 .L_OP_NEG_FLOAT: /* 0x7f */
   3623 /* File: armv5te/OP_NEG_FLOAT.S */
   3624 /* File: armv5te/unop.S */
   3625     /*
   3626      * Generic 32-bit unary operation.  Provide an "instr" line that
   3627      * specifies an instruction that performs "result = op r0".
   3628      * This could be an ARM instruction or a function call.
   3629      *
   3630      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3631      *      int-to-byte, int-to-char, int-to-short
   3632      */
   3633     /* unop vA, vB */
   3634     mov     r3, rINST, lsr #12          @ r3<- B
   3635     mov     r9, rINST, lsr #8           @ r9<- A+
   3636     GET_VREG(r0, r3)                    @ r0<- vB
   3637     and     r9, r9, #15
   3638                                @ optional op; may set condition codes
   3639     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3640     add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
   3641     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3642     SET_VREG(r0, r9)                    @ vAA<- r0
   3643     GOTO_OPCODE(ip)                     @ jump to next instruction
   3644     /* 9-10 instructions */
   3645 
   3646 
   3647 /* ------------------------------ */
   3648     .balign 64
   3649 .L_OP_NEG_DOUBLE: /* 0x80 */
   3650 /* File: armv5te/OP_NEG_DOUBLE.S */
   3651 /* File: armv5te/unopWide.S */
   3652     /*
   3653      * Generic 64-bit unary operation.  Provide an "instr" line that
   3654      * specifies an instruction that performs "result = op r0/r1".
   3655      * This could be an ARM instruction or a function call.
   3656      *
   3657      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3658      */
   3659     /* unop vA, vB */
   3660     mov     r9, rINST, lsr #8           @ r9<- A+
   3661     mov     r3, rINST, lsr #12          @ r3<- B
   3662     and     r9, r9, #15
   3663     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3664     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3665     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3666     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3667                                @ optional op; may set condition codes
   3668     add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
   3669     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3670     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3671     GOTO_OPCODE(ip)                     @ jump to next instruction
   3672     /* 12-13 instructions */
   3673 
   3674 
   3675 /* ------------------------------ */
   3676     .balign 64
   3677 .L_OP_INT_TO_LONG: /* 0x81 */
   3678 /* File: armv5te/OP_INT_TO_LONG.S */
   3679 /* File: armv5te/unopWider.S */
   3680     /*
   3681      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3682      * that specifies an instruction that performs "result = op r0", where
   3683      * "result" is a 64-bit quantity in r0/r1.
   3684      *
   3685      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3686      */
   3687     /* unop vA, vB */
   3688     mov     r9, rINST, lsr #8           @ r9<- A+
   3689     mov     r3, rINST, lsr #12          @ r3<- B
   3690     and     r9, r9, #15
   3691     GET_VREG(r0, r3)                    @ r0<- vB
   3692     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3693                                @ optional op; may set condition codes
   3694     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3695     mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
   3696     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3697     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3698     GOTO_OPCODE(ip)                     @ jump to next instruction
   3699     /* 10-11 instructions */
   3700 
   3701 
   3702 /* ------------------------------ */
   3703     .balign 64
   3704 .L_OP_INT_TO_FLOAT: /* 0x82 */
   3705 /* File: armv5te/OP_INT_TO_FLOAT.S */
   3706 /* File: armv5te/unop.S */
   3707     /*
   3708      * Generic 32-bit unary operation.  Provide an "instr" line that
   3709      * specifies an instruction that performs "result = op r0".
   3710      * This could be an ARM instruction or a function call.
   3711      *
   3712      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3713      *      int-to-byte, int-to-char, int-to-short
   3714      */
   3715     /* unop vA, vB */
   3716     mov     r3, rINST, lsr #12          @ r3<- B
   3717     mov     r9, rINST, lsr #8           @ r9<- A+
   3718     GET_VREG(r0, r3)                    @ r0<- vB
   3719     and     r9, r9, #15
   3720                                @ optional op; may set condition codes
   3721     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3722     bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
   3723     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3724     SET_VREG(r0, r9)                    @ vAA<- r0
   3725     GOTO_OPCODE(ip)                     @ jump to next instruction
   3726     /* 9-10 instructions */
   3727 
   3728 
   3729 /* ------------------------------ */
   3730     .balign 64
   3731 .L_OP_INT_TO_DOUBLE: /* 0x83 */
   3732 /* File: armv5te/OP_INT_TO_DOUBLE.S */
   3733 /* File: armv5te/unopWider.S */
   3734     /*
   3735      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3736      * that specifies an instruction that performs "result = op r0", where
   3737      * "result" is a 64-bit quantity in r0/r1.
   3738      *
   3739      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3740      */
   3741     /* unop vA, vB */
   3742     mov     r9, rINST, lsr #8           @ r9<- A+
   3743     mov     r3, rINST, lsr #12          @ r3<- B
   3744     and     r9, r9, #15
   3745     GET_VREG(r0, r3)                    @ r0<- vB
   3746     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3747                                @ optional op; may set condition codes
   3748     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3749     bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
   3750     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3751     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3752     GOTO_OPCODE(ip)                     @ jump to next instruction
   3753     /* 10-11 instructions */
   3754 
   3755 
   3756 /* ------------------------------ */
   3757     .balign 64
   3758 .L_OP_LONG_TO_INT: /* 0x84 */
   3759 /* File: armv5te/OP_LONG_TO_INT.S */
   3760 /* we ignore the high word, making this equivalent to a 32-bit reg move */
   3761 /* File: armv5te/OP_MOVE.S */
   3762     /* for move, move-object, long-to-int */
   3763     /* op vA, vB */
   3764     mov     r1, rINST, lsr #12          @ r1<- B from 15:12
   3765     mov     r0, rINST, lsr #8           @ r0<- A from 11:8
   3766     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3767     GET_VREG(r2, r1)                    @ r2<- fp[B]
   3768     and     r0, r0, #15
   3769     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
   3770     SET_VREG(r2, r0)                    @ fp[A]<- r2
   3771     GOTO_OPCODE(ip)                     @ execute next instruction
   3772 
   3773 
   3774 /* ------------------------------ */
   3775     .balign 64
   3776 .L_OP_LONG_TO_FLOAT: /* 0x85 */
   3777 /* File: armv5te/OP_LONG_TO_FLOAT.S */
   3778 /* File: armv5te/unopNarrower.S */
   3779     /*
   3780      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
   3781      * that specifies an instruction that performs "result = op r0/r1", where
   3782      * "result" is a 32-bit quantity in r0.
   3783      *
   3784      * For: long-to-float, double-to-int, double-to-float
   3785      *
   3786      * (This would work for long-to-int, but that instruction is actually
   3787      * an exact match for OP_MOVE.)
   3788      */
   3789     /* unop vA, vB */
   3790     mov     r3, rINST, lsr #12          @ r3<- B
   3791     mov     r9, rINST, lsr #8           @ r9<- A+
   3792     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3793     and     r9, r9, #15
   3794     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
   3795     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3796                                @ optional op; may set condition codes
   3797     bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
   3798     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3799     SET_VREG(r0, r9)                    @ vA<- r0
   3800     GOTO_OPCODE(ip)                     @ jump to next instruction
   3801     /* 10-11 instructions */
   3802 
   3803 
   3804 /* ------------------------------ */
   3805     .balign 64
   3806 .L_OP_LONG_TO_DOUBLE: /* 0x86 */
   3807 /* File: armv5te/OP_LONG_TO_DOUBLE.S */
   3808 /* File: armv5te/unopWide.S */
   3809     /*
   3810      * Generic 64-bit unary operation.  Provide an "instr" line that
   3811      * specifies an instruction that performs "result = op r0/r1".
   3812      * This could be an ARM instruction or a function call.
   3813      *
   3814      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   3815      */
   3816     /* unop vA, vB */
   3817     mov     r9, rINST, lsr #8           @ r9<- A+
   3818     mov     r3, rINST, lsr #12          @ r3<- B
   3819     and     r9, r9, #15
   3820     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3821     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3822     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   3823     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3824                                @ optional op; may set condition codes
   3825     bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
   3826     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3827     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   3828     GOTO_OPCODE(ip)                     @ jump to next instruction
   3829     /* 12-13 instructions */
   3830 
   3831 
   3832 /* ------------------------------ */
   3833     .balign 64
   3834 .L_OP_FLOAT_TO_INT: /* 0x87 */
   3835 /* File: armv5te/OP_FLOAT_TO_INT.S */
   3836 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
   3837 /* File: armv5te/unop.S */
   3838     /*
   3839      * Generic 32-bit unary operation.  Provide an "instr" line that
   3840      * specifies an instruction that performs "result = op r0".
   3841      * This could be an ARM instruction or a function call.
   3842      *
   3843      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   3844      *      int-to-byte, int-to-char, int-to-short
   3845      */
   3846     /* unop vA, vB */
   3847     mov     r3, rINST, lsr #12          @ r3<- B
   3848     mov     r9, rINST, lsr #8           @ r9<- A+
   3849     GET_VREG(r0, r3)                    @ r0<- vB
   3850     and     r9, r9, #15
   3851                                @ optional op; may set condition codes
   3852     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3853     bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
   3854     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3855     SET_VREG(r0, r9)                    @ vAA<- r0
   3856     GOTO_OPCODE(ip)                     @ jump to next instruction
   3857     /* 9-10 instructions */
   3858 
   3859 
   3860 #if 0
   3861 @include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
   3862 @break
   3863 /*
   3864  * Convert the float in r0 to an int in r0.
   3865  *
   3866  * We have to clip values to int min/max per the specification.  The
   3867  * expected common case is a "reasonable" value that converts directly
   3868  * to modest integer.  The EABI convert function isn't doing this for us.
   3869  */
   3870 f2i_doconv:
   3871     stmfd   sp!, {r4, lr}
   3872     mov     r1, #0x4f000000             @ (float)maxint
   3873     mov     r4, r0
   3874     bl      __aeabi_fcmpge              @ is arg >= maxint?
   3875     cmp     r0, #0                      @ nonzero == yes
   3876     mvnne   r0, #0x80000000             @ return maxint (7fffffff)
   3877     ldmnefd sp!, {r4, pc}
   3878 
   3879     mov     r0, r4                      @ recover arg
   3880     mov     r1, #0xcf000000             @ (float)minint
   3881     bl      __aeabi_fcmple              @ is arg <= minint?
   3882     cmp     r0, #0                      @ nonzero == yes
   3883     movne   r0, #0x80000000             @ return minint (80000000)
   3884     ldmnefd sp!, {r4, pc}
   3885 
   3886     mov     r0, r4                      @ recover arg
   3887     mov     r1, r4
   3888     bl      __aeabi_fcmpeq              @ is arg == self?
   3889     cmp     r0, #0                      @ zero == no
   3890     ldmeqfd sp!, {r4, pc}               @ return zero for NaN
   3891 
   3892     mov     r0, r4                      @ recover arg
   3893     bl      __aeabi_f2iz                @ convert float to int
   3894     ldmfd   sp!, {r4, pc}
   3895 #endif
   3896 
   3897 /* ------------------------------ */
   3898     .balign 64
   3899 .L_OP_FLOAT_TO_LONG: /* 0x88 */
   3900 /* File: armv5te/OP_FLOAT_TO_LONG.S */
   3901 @include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
   3902 /* File: armv5te/unopWider.S */
   3903     /*
   3904      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3905      * that specifies an instruction that performs "result = op r0", where
   3906      * "result" is a 64-bit quantity in r0/r1.
   3907      *
   3908      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3909      */
   3910     /* unop vA, vB */
   3911     mov     r9, rINST, lsr #8           @ r9<- A+
   3912     mov     r3, rINST, lsr #12          @ r3<- B
   3913     and     r9, r9, #15
   3914     GET_VREG(r0, r3)                    @ r0<- vB
   3915     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3916                                @ optional op; may set condition codes
   3917     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3918     bl      f2l_doconv                              @ r0<- op, r0-r3 changed
   3919     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3920     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3921     GOTO_OPCODE(ip)                     @ jump to next instruction
   3922     /* 10-11 instructions */
   3923 
   3924 
   3925 
   3926 /* ------------------------------ */
   3927     .balign 64
   3928 .L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
   3929 /* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
   3930 /* File: armv5te/unopWider.S */
   3931     /*
   3932      * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
   3933      * that specifies an instruction that performs "result = op r0", where
   3934      * "result" is a 64-bit quantity in r0/r1.
   3935      *
   3936      * For: int-to-long, int-to-double, float-to-long, float-to-double
   3937      */
   3938     /* unop vA, vB */
   3939     mov     r9, rINST, lsr #8           @ r9<- A+
   3940     mov     r3, rINST, lsr #12          @ r3<- B
   3941     and     r9, r9, #15
   3942     GET_VREG(r0, r3)                    @ r0<- vB
   3943     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   3944                                @ optional op; may set condition codes
   3945     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3946     bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
   3947     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3948     stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
   3949     GOTO_OPCODE(ip)                     @ jump to next instruction
   3950     /* 10-11 instructions */
   3951 
   3952 
   3953 /* ------------------------------ */
   3954     .balign 64
   3955 .L_OP_DOUBLE_TO_INT: /* 0x8a */
   3956 /* File: armv5te/OP_DOUBLE_TO_INT.S */
   3957 /* EABI appears to have Java-style conversions of +inf/-inf/NaN */
   3958 /* File: armv5te/unopNarrower.S */
   3959     /*
   3960      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
   3961      * that specifies an instruction that performs "result = op r0/r1", where
   3962      * "result" is a 32-bit quantity in r0.
   3963      *
   3964      * For: long-to-float, double-to-int, double-to-float
   3965      *
   3966      * (This would work for long-to-int, but that instruction is actually
   3967      * an exact match for OP_MOVE.)
   3968      */
   3969     /* unop vA, vB */
   3970     mov     r3, rINST, lsr #12          @ r3<- B
   3971     mov     r9, rINST, lsr #8           @ r9<- A+
   3972     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   3973     and     r9, r9, #15
   3974     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
   3975     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   3976                                @ optional op; may set condition codes
   3977     bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
   3978     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   3979     SET_VREG(r0, r9)                    @ vA<- r0
   3980     GOTO_OPCODE(ip)                     @ jump to next instruction
   3981     /* 10-11 instructions */
   3982 
   3983 
   3984 #if 0
   3985 @include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
   3986 @break
   3987 /*
   3988  * Convert the double in r0/r1 to an int in r0.
   3989  *
   3990  * We have to clip values to int min/max per the specification.  The
   3991  * expected common case is a "reasonable" value that converts directly
   3992  * to modest integer.  The EABI convert function isn't doing this for us.
   3993  */
   3994 d2i_doconv:
   3995     stmfd   sp!, {r4, r5, lr}           @ save regs
   3996     mov     r2, #0x80000000             @ maxint, as a double (low word)
   3997     mov     r2, r2, asr #9              @  0xffc00000
   3998     sub     sp, sp, #4                  @ align for EABI
   3999     mvn     r3, #0xbe000000             @ maxint, as a double (high word)
   4000     sub     r3, r3, #0x00200000         @  0x41dfffff
   4001     mov     r4, r0                      @ save a copy of r0
   4002     mov     r5, r1                      @  and r1
   4003     bl      __aeabi_dcmpge              @ is arg >= maxint?
   4004     cmp     r0, #0                      @ nonzero == yes
   4005     mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
   4006     bne     1f
   4007 
   4008     mov     r0, r4                      @ recover arg
   4009     mov     r1, r5
   4010     mov     r3, #0xc1000000             @ minint, as a double (high word)
   4011     add     r3, r3, #0x00e00000         @  0xc1e00000
   4012     mov     r2, #0                      @ minint, as a double (low word)
   4013     bl      __aeabi_dcmple              @ is arg <= minint?
   4014     cmp     r0, #0                      @ nonzero == yes
   4015     movne   r0, #0x80000000             @ return minint (80000000)
   4016     bne     1f
   4017 
   4018     mov     r0, r4                      @ recover arg
   4019     mov     r1, r5
   4020     mov     r2, r4                      @ compare against self
   4021     mov     r3, r5
   4022     bl      __aeabi_dcmpeq              @ is arg == self?
   4023     cmp     r0, #0                      @ zero == no
   4024     beq     1f                          @ return zero for NaN
   4025 
   4026     mov     r0, r4                      @ recover arg
   4027     mov     r1, r5
   4028     bl      __aeabi_d2iz                @ convert double to int
   4029 
   4030 1:
   4031     add     sp, sp, #4
   4032     ldmfd   sp!, {r4, r5, pc}
   4033 #endif
   4034 
   4035 /* ------------------------------ */
   4036     .balign 64
   4037 .L_OP_DOUBLE_TO_LONG: /* 0x8b */
   4038 /* File: armv5te/OP_DOUBLE_TO_LONG.S */
   4039 @include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
   4040 /* File: armv5te/unopWide.S */
   4041     /*
   4042      * Generic 64-bit unary operation.  Provide an "instr" line that
   4043      * specifies an instruction that performs "result = op r0/r1".
   4044      * This could be an ARM instruction or a function call.
   4045      *
   4046      * For: neg-long, not-long, neg-double, long-to-double, double-to-long
   4047      */
   4048     /* unop vA, vB */
   4049     mov     r9, rINST, lsr #8           @ r9<- A+
   4050     mov     r3, rINST, lsr #12          @ r3<- B
   4051     and     r9, r9, #15
   4052     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   4053     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   4054     ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
   4055     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4056                                @ optional op; may set condition codes
   4057     bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
   4058     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4059     stmia   r9, {r0-r1}                 @ vAA<- r0/r1
   4060     GOTO_OPCODE(ip)                     @ jump to next instruction
   4061     /* 12-13 instructions */
   4062 
   4063 
   4064 
   4065 /* ------------------------------ */
   4066     .balign 64
   4067 .L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
   4068 /* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
   4069 /* File: armv5te/unopNarrower.S */
   4070     /*
   4071      * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
   4072      * that specifies an instruction that performs "result = op r0/r1", where
   4073      * "result" is a 32-bit quantity in r0.
   4074      *
   4075      * For: long-to-float, double-to-int, double-to-float
   4076      *
   4077      * (This would work for long-to-int, but that instruction is actually
   4078      * an exact match for OP_MOVE.)
   4079      */
   4080     /* unop vA, vB */
   4081     mov     r3, rINST, lsr #12          @ r3<- B
   4082     mov     r9, rINST, lsr #8           @ r9<- A+
   4083     add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
   4084     and     r9, r9, #15
   4085     ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
   4086     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4087                                @ optional op; may set condition codes
   4088     bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
   4089     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4090     SET_VREG(r0, r9)                    @ vA<- r0
   4091     GOTO_OPCODE(ip)                     @ jump to next instruction
   4092     /* 10-11 instructions */
   4093 
   4094 
   4095 /* ------------------------------ */
   4096     .balign 64
   4097 .L_OP_INT_TO_BYTE: /* 0x8d */
   4098 /* File: armv5te/OP_INT_TO_BYTE.S */
   4099 /* File: armv5te/unop.S */
   4100     /*
   4101      * Generic 32-bit unary operation.  Provide an "instr" line that
   4102      * specifies an instruction that performs "result = op r0".
   4103      * This could be an ARM instruction or a function call.
   4104      *
   4105      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   4106      *      int-to-byte, int-to-char, int-to-short
   4107      */
   4108     /* unop vA, vB */
   4109     mov     r3, rINST, lsr #12          @ r3<- B
   4110     mov     r9, rINST, lsr #8           @ r9<- A+
   4111     GET_VREG(r0, r3)                    @ r0<- vB
   4112     and     r9, r9, #15
   4113     mov     r0, r0, asl #24                           @ optional op; may set condition codes
   4114     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4115     mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
   4116     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4117     SET_VREG(r0, r9)                    @ vAA<- r0
   4118     GOTO_OPCODE(ip)                     @ jump to next instruction
   4119     /* 9-10 instructions */
   4120 
   4121 
   4122 /* ------------------------------ */
   4123     .balign 64
   4124 .L_OP_INT_TO_CHAR: /* 0x8e */
   4125 /* File: armv5te/OP_INT_TO_CHAR.S */
   4126 /* File: armv5te/unop.S */
   4127     /*
   4128      * Generic 32-bit unary operation.  Provide an "instr" line that
   4129      * specifies an instruction that performs "result = op r0".
   4130      * This could be an ARM instruction or a function call.
   4131      *
   4132      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   4133      *      int-to-byte, int-to-char, int-to-short
   4134      */
   4135     /* unop vA, vB */
   4136     mov     r3, rINST, lsr #12          @ r3<- B
   4137     mov     r9, rINST, lsr #8           @ r9<- A+
   4138     GET_VREG(r0, r3)                    @ r0<- vB
   4139     and     r9, r9, #15
   4140     mov     r0, r0, asl #16                           @ optional op; may set condition codes
   4141     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4142     mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
   4143     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4144     SET_VREG(r0, r9)                    @ vAA<- r0
   4145     GOTO_OPCODE(ip)                     @ jump to next instruction
   4146     /* 9-10 instructions */
   4147 
   4148 
   4149 /* ------------------------------ */
   4150     .balign 64
   4151 .L_OP_INT_TO_SHORT: /* 0x8f */
   4152 /* File: armv5te/OP_INT_TO_SHORT.S */
   4153 /* File: armv5te/unop.S */
   4154     /*
   4155      * Generic 32-bit unary operation.  Provide an "instr" line that
   4156      * specifies an instruction that performs "result = op r0".
   4157      * This could be an ARM instruction or a function call.
   4158      *
   4159      * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
   4160      *      int-to-byte, int-to-char, int-to-short
   4161      */
   4162     /* unop vA, vB */
   4163     mov     r3, rINST, lsr #12          @ r3<- B
   4164     mov     r9, rINST, lsr #8           @ r9<- A+
   4165     GET_VREG(r0, r3)                    @ r0<- vB
   4166     and     r9, r9, #15
   4167     mov     r0, r0, asl #16                           @ optional op; may set condition codes
   4168     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   4169     mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
   4170     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4171     SET_VREG(r0, r9)                    @ vAA<- r0
   4172     GOTO_OPCODE(ip)                     @ jump to next instruction
   4173     /* 9-10 instructions */
   4174 
   4175 
   4176 /* ------------------------------ */
   4177     .balign 64
   4178 .L_OP_ADD_INT: /* 0x90 */
   4179 /* File: armv5te/OP_ADD_INT.S */
   4180 /* File: armv5te/binop.S */
   4181     /*
   4182      * Generic 32-bit binary operation.  Provide an "instr" line that
   4183      * specifies an instruction that performs "result = r0 op r1".
   4184      * This could be an ARM instruction or a function call.  (If the result
   4185      * comes back in a register other than r0, you can override "result".)
   4186      *
   4187      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4188      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4189      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4190      * handles it correctly.
   4191      *
   4192      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4193      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4194      *      mul-float, div-float, rem-float
   4195      */
   4196     /* binop vAA, vBB, vCC */
   4197     FETCH(r0, 1)                        @ r0<- CCBB
   4198     mov     r9, rINST, lsr #8           @ r9<- AA
   4199     mov     r3, r0, lsr #8              @ r3<- CC
   4200     and     r2, r0, #255                @ r2<- BB
   4201     GET_VREG(r1, r3)                    @ r1<- vCC
   4202     GET_VREG(r0, r2)                    @ r0<- vBB
   4203     .if 0
   4204     cmp     r1, #0                      @ is second operand zero?
   4205     beq     common_errDivideByZero
   4206     .endif
   4207 
   4208     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4209                                @ optional op; may set condition codes
   4210     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4211     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4212     SET_VREG(r0, r9)               @ vAA<- r0
   4213     GOTO_OPCODE(ip)                     @ jump to next instruction
   4214     /* 11-14 instructions */
   4215 
   4216 
   4217 /* ------------------------------ */
   4218     .balign 64
   4219 .L_OP_SUB_INT: /* 0x91 */
   4220 /* File: armv5te/OP_SUB_INT.S */
   4221 /* File: armv5te/binop.S */
   4222     /*
   4223      * Generic 32-bit binary operation.  Provide an "instr" line that
   4224      * specifies an instruction that performs "result = r0 op r1".
   4225      * This could be an ARM instruction or a function call.  (If the result
   4226      * comes back in a register other than r0, you can override "result".)
   4227      *
   4228      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4229      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4230      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4231      * handles it correctly.
   4232      *
   4233      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4234      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4235      *      mul-float, div-float, rem-float
   4236      */
   4237     /* binop vAA, vBB, vCC */
   4238     FETCH(r0, 1)                        @ r0<- CCBB
   4239     mov     r9, rINST, lsr #8           @ r9<- AA
   4240     mov     r3, r0, lsr #8              @ r3<- CC
   4241     and     r2, r0, #255                @ r2<- BB
   4242     GET_VREG(r1, r3)                    @ r1<- vCC
   4243     GET_VREG(r0, r2)                    @ r0<- vBB
   4244     .if 0
   4245     cmp     r1, #0                      @ is second operand zero?
   4246     beq     common_errDivideByZero
   4247     .endif
   4248 
   4249     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4250                                @ optional op; may set condition codes
   4251     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4252     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4253     SET_VREG(r0, r9)               @ vAA<- r0
   4254     GOTO_OPCODE(ip)                     @ jump to next instruction
   4255     /* 11-14 instructions */
   4256 
   4257 
   4258 /* ------------------------------ */
   4259     .balign 64
   4260 .L_OP_MUL_INT: /* 0x92 */
   4261 /* File: armv5te/OP_MUL_INT.S */
   4262 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   4263 /* File: armv5te/binop.S */
   4264     /*
   4265      * Generic 32-bit binary operation.  Provide an "instr" line that
   4266      * specifies an instruction that performs "result = r0 op r1".
   4267      * This could be an ARM instruction or a function call.  (If the result
   4268      * comes back in a register other than r0, you can override "result".)
   4269      *
   4270      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4271      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4272      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4273      * handles it correctly.
   4274      *
   4275      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4276      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4277      *      mul-float, div-float, rem-float
   4278      */
   4279     /* binop vAA, vBB, vCC */
   4280     FETCH(r0, 1)                        @ r0<- CCBB
   4281     mov     r9, rINST, lsr #8           @ r9<- AA
   4282     mov     r3, r0, lsr #8              @ r3<- CC
   4283     and     r2, r0, #255                @ r2<- BB
   4284     GET_VREG(r1, r3)                    @ r1<- vCC
   4285     GET_VREG(r0, r2)                    @ r0<- vBB
   4286     .if 0
   4287     cmp     r1, #0                      @ is second operand zero?
   4288     beq     common_errDivideByZero
   4289     .endif
   4290 
   4291     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4292                                @ optional op; may set condition codes
   4293     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   4294     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4295     SET_VREG(r0, r9)               @ vAA<- r0
   4296     GOTO_OPCODE(ip)                     @ jump to next instruction
   4297     /* 11-14 instructions */
   4298 
   4299 
   4300 /* ------------------------------ */
   4301     .balign 64
   4302 .L_OP_DIV_INT: /* 0x93 */
   4303 /* File: armv5te/OP_DIV_INT.S */
   4304 /* File: armv5te/binop.S */
   4305     /*
   4306      * Generic 32-bit binary operation.  Provide an "instr" line that
   4307      * specifies an instruction that performs "result = r0 op r1".
   4308      * This could be an ARM instruction or a function call.  (If the result
   4309      * comes back in a register other than r0, you can override "result".)
   4310      *
   4311      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4312      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4313      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4314      * handles it correctly.
   4315      *
   4316      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4317      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4318      *      mul-float, div-float, rem-float
   4319      */
   4320     /* binop vAA, vBB, vCC */
   4321     FETCH(r0, 1)                        @ r0<- CCBB
   4322     mov     r9, rINST, lsr #8           @ r9<- AA
   4323     mov     r3, r0, lsr #8              @ r3<- CC
   4324     and     r2, r0, #255                @ r2<- BB
   4325     GET_VREG(r1, r3)                    @ r1<- vCC
   4326     GET_VREG(r0, r2)                    @ r0<- vBB
   4327     .if 1
   4328     cmp     r1, #0                      @ is second operand zero?
   4329     beq     common_errDivideByZero
   4330     .endif
   4331 
   4332     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4333                                @ optional op; may set condition codes
   4334     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   4335     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4336     SET_VREG(r0, r9)               @ vAA<- r0
   4337     GOTO_OPCODE(ip)                     @ jump to next instruction
   4338     /* 11-14 instructions */
   4339 
   4340 
   4341 /* ------------------------------ */
   4342     .balign 64
   4343 .L_OP_REM_INT: /* 0x94 */
   4344 /* File: armv5te/OP_REM_INT.S */
   4345 /* idivmod returns quotient in r0 and remainder in r1 */
   4346 /* File: armv5te/binop.S */
   4347     /*
   4348      * Generic 32-bit binary operation.  Provide an "instr" line that
   4349      * specifies an instruction that performs "result = r0 op r1".
   4350      * This could be an ARM instruction or a function call.  (If the result
   4351      * comes back in a register other than r0, you can override "result".)
   4352      *
   4353      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4354      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4355      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4356      * handles it correctly.
   4357      *
   4358      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4359      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4360      *      mul-float, div-float, rem-float
   4361      */
   4362     /* binop vAA, vBB, vCC */
   4363     FETCH(r0, 1)                        @ r0<- CCBB
   4364     mov     r9, rINST, lsr #8           @ r9<- AA
   4365     mov     r3, r0, lsr #8              @ r3<- CC
   4366     and     r2, r0, #255                @ r2<- BB
   4367     GET_VREG(r1, r3)                    @ r1<- vCC
   4368     GET_VREG(r0, r2)                    @ r0<- vBB
   4369     .if 1
   4370     cmp     r1, #0                      @ is second operand zero?
   4371     beq     common_errDivideByZero
   4372     .endif
   4373 
   4374     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4375                                @ optional op; may set condition codes
   4376     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   4377     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4378     SET_VREG(r1, r9)               @ vAA<- r1
   4379     GOTO_OPCODE(ip)                     @ jump to next instruction
   4380     /* 11-14 instructions */
   4381 
   4382 
   4383 /* ------------------------------ */
   4384     .balign 64
   4385 .L_OP_AND_INT: /* 0x95 */
   4386 /* File: armv5te/OP_AND_INT.S */
   4387 /* File: armv5te/binop.S */
   4388     /*
   4389      * Generic 32-bit binary operation.  Provide an "instr" line that
   4390      * specifies an instruction that performs "result = r0 op r1".
   4391      * This could be an ARM instruction or a function call.  (If the result
   4392      * comes back in a register other than r0, you can override "result".)
   4393      *
   4394      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4395      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4396      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4397      * handles it correctly.
   4398      *
   4399      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4400      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4401      *      mul-float, div-float, rem-float
   4402      */
   4403     /* binop vAA, vBB, vCC */
   4404     FETCH(r0, 1)                        @ r0<- CCBB
   4405     mov     r9, rINST, lsr #8           @ r9<- AA
   4406     mov     r3, r0, lsr #8              @ r3<- CC
   4407     and     r2, r0, #255                @ r2<- BB
   4408     GET_VREG(r1, r3)                    @ r1<- vCC
   4409     GET_VREG(r0, r2)                    @ r0<- vBB
   4410     .if 0
   4411     cmp     r1, #0                      @ is second operand zero?
   4412     beq     common_errDivideByZero
   4413     .endif
   4414 
   4415     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4416                                @ optional op; may set condition codes
   4417     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4418     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4419     SET_VREG(r0, r9)               @ vAA<- r0
   4420     GOTO_OPCODE(ip)                     @ jump to next instruction
   4421     /* 11-14 instructions */
   4422 
   4423 
   4424 /* ------------------------------ */
   4425     .balign 64
   4426 .L_OP_OR_INT: /* 0x96 */
   4427 /* File: armv5te/OP_OR_INT.S */
   4428 /* File: armv5te/binop.S */
   4429     /*
   4430      * Generic 32-bit binary operation.  Provide an "instr" line that
   4431      * specifies an instruction that performs "result = r0 op r1".
   4432      * This could be an ARM instruction or a function call.  (If the result
   4433      * comes back in a register other than r0, you can override "result".)
   4434      *
   4435      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4436      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4437      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4438      * handles it correctly.
   4439      *
   4440      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4441      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4442      *      mul-float, div-float, rem-float
   4443      */
   4444     /* binop vAA, vBB, vCC */
   4445     FETCH(r0, 1)                        @ r0<- CCBB
   4446     mov     r9, rINST, lsr #8           @ r9<- AA
   4447     mov     r3, r0, lsr #8              @ r3<- CC
   4448     and     r2, r0, #255                @ r2<- BB
   4449     GET_VREG(r1, r3)                    @ r1<- vCC
   4450     GET_VREG(r0, r2)                    @ r0<- vBB
   4451     .if 0
   4452     cmp     r1, #0                      @ is second operand zero?
   4453     beq     common_errDivideByZero
   4454     .endif
   4455 
   4456     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4457                                @ optional op; may set condition codes
   4458     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4459     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4460     SET_VREG(r0, r9)               @ vAA<- r0
   4461     GOTO_OPCODE(ip)                     @ jump to next instruction
   4462     /* 11-14 instructions */
   4463 
   4464 
   4465 /* ------------------------------ */
   4466     .balign 64
   4467 .L_OP_XOR_INT: /* 0x97 */
   4468 /* File: armv5te/OP_XOR_INT.S */
   4469 /* File: armv5te/binop.S */
   4470     /*
   4471      * Generic 32-bit binary operation.  Provide an "instr" line that
   4472      * specifies an instruction that performs "result = r0 op r1".
   4473      * This could be an ARM instruction or a function call.  (If the result
   4474      * comes back in a register other than r0, you can override "result".)
   4475      *
   4476      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4477      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4478      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4479      * handles it correctly.
   4480      *
   4481      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4482      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4483      *      mul-float, div-float, rem-float
   4484      */
   4485     /* binop vAA, vBB, vCC */
   4486     FETCH(r0, 1)                        @ r0<- CCBB
   4487     mov     r9, rINST, lsr #8           @ r9<- AA
   4488     mov     r3, r0, lsr #8              @ r3<- CC
   4489     and     r2, r0, #255                @ r2<- BB
   4490     GET_VREG(r1, r3)                    @ r1<- vCC
   4491     GET_VREG(r0, r2)                    @ r0<- vBB
   4492     .if 0
   4493     cmp     r1, #0                      @ is second operand zero?
   4494     beq     common_errDivideByZero
   4495     .endif
   4496 
   4497     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4498                                @ optional op; may set condition codes
   4499     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   4500     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4501     SET_VREG(r0, r9)               @ vAA<- r0
   4502     GOTO_OPCODE(ip)                     @ jump to next instruction
   4503     /* 11-14 instructions */
   4504 
   4505 
   4506 /* ------------------------------ */
   4507     .balign 64
   4508 .L_OP_SHL_INT: /* 0x98 */
   4509 /* File: armv5te/OP_SHL_INT.S */
   4510 /* File: armv5te/binop.S */
   4511     /*
   4512      * Generic 32-bit binary operation.  Provide an "instr" line that
   4513      * specifies an instruction that performs "result = r0 op r1".
   4514      * This could be an ARM instruction or a function call.  (If the result
   4515      * comes back in a register other than r0, you can override "result".)
   4516      *
   4517      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4518      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4519      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4520      * handles it correctly.
   4521      *
   4522      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4523      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4524      *      mul-float, div-float, rem-float
   4525      */
   4526     /* binop vAA, vBB, vCC */
   4527     FETCH(r0, 1)                        @ r0<- CCBB
   4528     mov     r9, rINST, lsr #8           @ r9<- AA
   4529     mov     r3, r0, lsr #8              @ r3<- CC
   4530     and     r2, r0, #255                @ r2<- BB
   4531     GET_VREG(r1, r3)                    @ r1<- vCC
   4532     GET_VREG(r0, r2)                    @ r0<- vBB
   4533     .if 0
   4534     cmp     r1, #0                      @ is second operand zero?
   4535     beq     common_errDivideByZero
   4536     .endif
   4537 
   4538     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4539     and     r1, r1, #31                           @ optional op; may set condition codes
   4540     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   4541     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4542     SET_VREG(r0, r9)               @ vAA<- r0
   4543     GOTO_OPCODE(ip)                     @ jump to next instruction
   4544     /* 11-14 instructions */
   4545 
   4546 
   4547 /* ------------------------------ */
   4548     .balign 64
   4549 .L_OP_SHR_INT: /* 0x99 */
   4550 /* File: armv5te/OP_SHR_INT.S */
   4551 /* File: armv5te/binop.S */
   4552     /*
   4553      * Generic 32-bit binary operation.  Provide an "instr" line that
   4554      * specifies an instruction that performs "result = r0 op r1".
   4555      * This could be an ARM instruction or a function call.  (If the result
   4556      * comes back in a register other than r0, you can override "result".)
   4557      *
   4558      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4559      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4560      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4561      * handles it correctly.
   4562      *
   4563      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4564      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4565      *      mul-float, div-float, rem-float
   4566      */
   4567     /* binop vAA, vBB, vCC */
   4568     FETCH(r0, 1)                        @ r0<- CCBB
   4569     mov     r9, rINST, lsr #8           @ r9<- AA
   4570     mov     r3, r0, lsr #8              @ r3<- CC
   4571     and     r2, r0, #255                @ r2<- BB
   4572     GET_VREG(r1, r3)                    @ r1<- vCC
   4573     GET_VREG(r0, r2)                    @ r0<- vBB
   4574     .if 0
   4575     cmp     r1, #0                      @ is second operand zero?
   4576     beq     common_errDivideByZero
   4577     .endif
   4578 
   4579     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4580     and     r1, r1, #31                           @ optional op; may set condition codes
   4581     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   4582     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4583     SET_VREG(r0, r9)               @ vAA<- r0
   4584     GOTO_OPCODE(ip)                     @ jump to next instruction
   4585     /* 11-14 instructions */
   4586 
   4587 
   4588 /* ------------------------------ */
   4589     .balign 64
   4590 .L_OP_USHR_INT: /* 0x9a */
   4591 /* File: armv5te/OP_USHR_INT.S */
   4592 /* File: armv5te/binop.S */
   4593     /*
   4594      * Generic 32-bit binary operation.  Provide an "instr" line that
   4595      * specifies an instruction that performs "result = r0 op r1".
   4596      * This could be an ARM instruction or a function call.  (If the result
   4597      * comes back in a register other than r0, you can override "result".)
   4598      *
   4599      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4600      * vCC (r1).  Useful for integer division and modulus.  Note that we
   4601      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   4602      * handles it correctly.
   4603      *
   4604      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   4605      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   4606      *      mul-float, div-float, rem-float
   4607      */
   4608     /* binop vAA, vBB, vCC */
   4609     FETCH(r0, 1)                        @ r0<- CCBB
   4610     mov     r9, rINST, lsr #8           @ r9<- AA
   4611     mov     r3, r0, lsr #8              @ r3<- CC
   4612     and     r2, r0, #255                @ r2<- BB
   4613     GET_VREG(r1, r3)                    @ r1<- vCC
   4614     GET_VREG(r0, r2)                    @ r0<- vBB
   4615     .if 0
   4616     cmp     r1, #0                      @ is second operand zero?
   4617     beq     common_errDivideByZero
   4618     .endif
   4619 
   4620     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4621     and     r1, r1, #31                           @ optional op; may set condition codes
   4622     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   4623     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4624     SET_VREG(r0, r9)               @ vAA<- r0
   4625     GOTO_OPCODE(ip)                     @ jump to next instruction
   4626     /* 11-14 instructions */
   4627 
   4628 
   4629 /* ------------------------------ */
   4630     .balign 64
   4631 .L_OP_ADD_LONG: /* 0x9b */
   4632 /* File: armv5te/OP_ADD_LONG.S */
   4633 /* File: armv5te/binopWide.S */
   4634     /*
   4635      * Generic 64-bit binary operation.  Provide an "instr" line that
   4636      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4637      * This could be an ARM instruction or a function call.  (If the result
   4638      * comes back in a register other than r0, you can override "result".)
   4639      *
   4640      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4641      * vCC (r1).  Useful for integer division and modulus.
   4642      *
   4643      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4644      *      xor-long, add-double, sub-double, mul-double, div-double,
   4645      *      rem-double
   4646      *
   4647      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4648      */
   4649     /* binop vAA, vBB, vCC */
   4650     FETCH(r0, 1)                        @ r0<- CCBB
   4651     mov     r9, rINST, lsr #8           @ r9<- AA
   4652     and     r2, r0, #255                @ r2<- BB
   4653     mov     r3, r0, lsr #8              @ r3<- CC
   4654     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4655     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4656     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4657     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4658     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4659     .if 0
   4660     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4661     beq     common_errDivideByZero
   4662     .endif
   4663     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4664 
   4665     adds    r0, r0, r2                           @ optional op; may set condition codes
   4666     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
   4667     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4668     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4669     GOTO_OPCODE(ip)                     @ jump to next instruction
   4670     /* 14-17 instructions */
   4671 
   4672 
   4673 /* ------------------------------ */
   4674     .balign 64
   4675 .L_OP_SUB_LONG: /* 0x9c */
   4676 /* File: armv5te/OP_SUB_LONG.S */
   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 0
   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     subs    r0, r0, r2                           @ optional op; may set condition codes
   4710     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
   4711     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4712     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4713     GOTO_OPCODE(ip)                     @ jump to next instruction
   4714     /* 14-17 instructions */
   4715 
   4716 
   4717 /* ------------------------------ */
   4718     .balign 64
   4719 .L_OP_MUL_LONG: /* 0x9d */
   4720 /* File: armv5te/OP_MUL_LONG.S */
   4721     /*
   4722      * Signed 64-bit integer multiply.
   4723      *
   4724      * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
   4725      *        WX
   4726      *      x YZ
   4727      *  --------
   4728      *     ZW ZX
   4729      *  YW YX
   4730      *
   4731      * The low word of the result holds ZX, the high word holds
   4732      * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
   4733      * it doesn't fit in the low 64 bits.
   4734      *
   4735      * Unlike most ARM math operations, multiply instructions have
   4736      * restrictions on using the same register more than once (Rd and Rm
   4737      * cannot be the same).
   4738      */
   4739     /* mul-long vAA, vBB, vCC */
   4740     FETCH(r0, 1)                        @ r0<- CCBB
   4741     and     r2, r0, #255                @ r2<- BB
   4742     mov     r3, r0, lsr #8              @ r3<- CC
   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     mul     ip, r2, r1                  @  ip<- ZxW
   4748     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
   4749     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
   4750     mov     r0, rINST, lsr #8           @ r0<- AA
   4751     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
   4752     add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
   4753     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4754     b       .LOP_MUL_LONG_finish
   4755 
   4756 /* ------------------------------ */
   4757     .balign 64
   4758 .L_OP_DIV_LONG: /* 0x9e */
   4759 /* File: armv5te/OP_DIV_LONG.S */
   4760 /* File: armv5te/binopWide.S */
   4761     /*
   4762      * Generic 64-bit binary operation.  Provide an "instr" line that
   4763      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4764      * This could be an ARM instruction or a function call.  (If the result
   4765      * comes back in a register other than r0, you can override "result".)
   4766      *
   4767      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4768      * vCC (r1).  Useful for integer division and modulus.
   4769      *
   4770      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4771      *      xor-long, add-double, sub-double, mul-double, div-double,
   4772      *      rem-double
   4773      *
   4774      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4775      */
   4776     /* binop vAA, vBB, vCC */
   4777     FETCH(r0, 1)                        @ r0<- CCBB
   4778     mov     r9, rINST, lsr #8           @ r9<- AA
   4779     and     r2, r0, #255                @ r2<- BB
   4780     mov     r3, r0, lsr #8              @ r3<- CC
   4781     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4782     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4783     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4784     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4785     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4786     .if 1
   4787     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4788     beq     common_errDivideByZero
   4789     .endif
   4790     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4791 
   4792                                @ optional op; may set condition codes
   4793     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   4794     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4795     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4796     GOTO_OPCODE(ip)                     @ jump to next instruction
   4797     /* 14-17 instructions */
   4798 
   4799 
   4800 /* ------------------------------ */
   4801     .balign 64
   4802 .L_OP_REM_LONG: /* 0x9f */
   4803 /* File: armv5te/OP_REM_LONG.S */
   4804 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
   4805 /* File: armv5te/binopWide.S */
   4806     /*
   4807      * Generic 64-bit binary operation.  Provide an "instr" line that
   4808      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4809      * This could be an ARM instruction or a function call.  (If the result
   4810      * comes back in a register other than r0, you can override "result".)
   4811      *
   4812      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4813      * vCC (r1).  Useful for integer division and modulus.
   4814      *
   4815      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4816      *      xor-long, add-double, sub-double, mul-double, div-double,
   4817      *      rem-double
   4818      *
   4819      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4820      */
   4821     /* binop vAA, vBB, vCC */
   4822     FETCH(r0, 1)                        @ r0<- CCBB
   4823     mov     r9, rINST, lsr #8           @ r9<- AA
   4824     and     r2, r0, #255                @ r2<- BB
   4825     mov     r3, r0, lsr #8              @ r3<- CC
   4826     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4827     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4828     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4829     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4830     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4831     .if 1
   4832     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4833     beq     common_errDivideByZero
   4834     .endif
   4835     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4836 
   4837                                @ optional op; may set condition codes
   4838     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   4839     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4840     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
   4841     GOTO_OPCODE(ip)                     @ jump to next instruction
   4842     /* 14-17 instructions */
   4843 
   4844 
   4845 /* ------------------------------ */
   4846     .balign 64
   4847 .L_OP_AND_LONG: /* 0xa0 */
   4848 /* File: armv5te/OP_AND_LONG.S */
   4849 /* File: armv5te/binopWide.S */
   4850     /*
   4851      * Generic 64-bit binary operation.  Provide an "instr" line that
   4852      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4853      * This could be an ARM instruction or a function call.  (If the result
   4854      * comes back in a register other than r0, you can override "result".)
   4855      *
   4856      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4857      * vCC (r1).  Useful for integer division and modulus.
   4858      *
   4859      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4860      *      xor-long, add-double, sub-double, mul-double, div-double,
   4861      *      rem-double
   4862      *
   4863      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4864      */
   4865     /* binop vAA, vBB, vCC */
   4866     FETCH(r0, 1)                        @ r0<- CCBB
   4867     mov     r9, rINST, lsr #8           @ r9<- AA
   4868     and     r2, r0, #255                @ r2<- BB
   4869     mov     r3, r0, lsr #8              @ r3<- CC
   4870     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4871     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4872     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4873     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4874     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4875     .if 0
   4876     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4877     beq     common_errDivideByZero
   4878     .endif
   4879     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4880 
   4881     and     r0, r0, r2                           @ optional op; may set condition codes
   4882     and     r1, r1, r3                              @ result<- op, r0-r3 changed
   4883     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4884     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4885     GOTO_OPCODE(ip)                     @ jump to next instruction
   4886     /* 14-17 instructions */
   4887 
   4888 
   4889 /* ------------------------------ */
   4890     .balign 64
   4891 .L_OP_OR_LONG: /* 0xa1 */
   4892 /* File: armv5te/OP_OR_LONG.S */
   4893 /* File: armv5te/binopWide.S */
   4894     /*
   4895      * Generic 64-bit binary operation.  Provide an "instr" line that
   4896      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4897      * This could be an ARM instruction or a function call.  (If the result
   4898      * comes back in a register other than r0, you can override "result".)
   4899      *
   4900      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4901      * vCC (r1).  Useful for integer division and modulus.
   4902      *
   4903      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4904      *      xor-long, add-double, sub-double, mul-double, div-double,
   4905      *      rem-double
   4906      *
   4907      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4908      */
   4909     /* binop vAA, vBB, vCC */
   4910     FETCH(r0, 1)                        @ r0<- CCBB
   4911     mov     r9, rINST, lsr #8           @ r9<- AA
   4912     and     r2, r0, #255                @ r2<- BB
   4913     mov     r3, r0, lsr #8              @ r3<- CC
   4914     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4915     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4916     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4917     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4918     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4919     .if 0
   4920     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4921     beq     common_errDivideByZero
   4922     .endif
   4923     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4924 
   4925     orr     r0, r0, r2                           @ optional op; may set condition codes
   4926     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
   4927     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4928     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4929     GOTO_OPCODE(ip)                     @ jump to next instruction
   4930     /* 14-17 instructions */
   4931 
   4932 
   4933 /* ------------------------------ */
   4934     .balign 64
   4935 .L_OP_XOR_LONG: /* 0xa2 */
   4936 /* File: armv5te/OP_XOR_LONG.S */
   4937 /* File: armv5te/binopWide.S */
   4938     /*
   4939      * Generic 64-bit binary operation.  Provide an "instr" line that
   4940      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   4941      * This could be an ARM instruction or a function call.  (If the result
   4942      * comes back in a register other than r0, you can override "result".)
   4943      *
   4944      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   4945      * vCC (r1).  Useful for integer division and modulus.
   4946      *
   4947      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   4948      *      xor-long, add-double, sub-double, mul-double, div-double,
   4949      *      rem-double
   4950      *
   4951      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   4952      */
   4953     /* binop vAA, vBB, vCC */
   4954     FETCH(r0, 1)                        @ r0<- CCBB
   4955     mov     r9, rINST, lsr #8           @ r9<- AA
   4956     and     r2, r0, #255                @ r2<- BB
   4957     mov     r3, r0, lsr #8              @ r3<- CC
   4958     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4959     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   4960     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   4961     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4962     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   4963     .if 0
   4964     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   4965     beq     common_errDivideByZero
   4966     .endif
   4967     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   4968 
   4969     eor     r0, r0, r2                           @ optional op; may set condition codes
   4970     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
   4971     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   4972     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   4973     GOTO_OPCODE(ip)                     @ jump to next instruction
   4974     /* 14-17 instructions */
   4975 
   4976 
   4977 /* ------------------------------ */
   4978     .balign 64
   4979 .L_OP_SHL_LONG: /* 0xa3 */
   4980 /* File: armv5te/OP_SHL_LONG.S */
   4981     /*
   4982      * Long integer shift.  This is different from the generic 32/64-bit
   4983      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   4984      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   4985      * 6 bits of the shift distance.
   4986      */
   4987     /* shl-long vAA, vBB, vCC */
   4988     FETCH(r0, 1)                        @ r0<- CCBB
   4989     mov     r9, rINST, lsr #8           @ r9<- AA
   4990     and     r3, r0, #255                @ r3<- BB
   4991     mov     r0, r0, lsr #8              @ r0<- CC
   4992     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   4993     GET_VREG(r2, r0)                    @ r2<- vCC
   4994     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   4995     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   4996     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   4997 
   4998     mov     r1, r1, asl r2              @  r1<- r1 << r2
   4999     rsb     r3, r2, #32                 @  r3<- 32 - r2
   5000     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
   5001     subs    ip, r2, #32                 @  ip<- r2 - 32
   5002     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
   5003     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5004     b       .LOP_SHL_LONG_finish
   5005 
   5006 /* ------------------------------ */
   5007     .balign 64
   5008 .L_OP_SHR_LONG: /* 0xa4 */
   5009 /* File: armv5te/OP_SHR_LONG.S */
   5010     /*
   5011      * Long integer shift.  This is different from the generic 32/64-bit
   5012      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   5013      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   5014      * 6 bits of the shift distance.
   5015      */
   5016     /* shr-long vAA, vBB, vCC */
   5017     FETCH(r0, 1)                        @ r0<- CCBB
   5018     mov     r9, rINST, lsr #8           @ r9<- AA
   5019     and     r3, r0, #255                @ r3<- BB
   5020     mov     r0, r0, lsr #8              @ r0<- CC
   5021     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   5022     GET_VREG(r2, r0)                    @ r2<- vCC
   5023     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5024     and     r2, r2, #63                 @ r0<- r0 & 0x3f
   5025     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5026 
   5027     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   5028     rsb     r3, r2, #32                 @  r3<- 32 - r2
   5029     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   5030     subs    ip, r2, #32                 @  ip<- r2 - 32
   5031     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
   5032     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5033     b       .LOP_SHR_LONG_finish
   5034 
   5035 /* ------------------------------ */
   5036     .balign 64
   5037 .L_OP_USHR_LONG: /* 0xa5 */
   5038 /* File: armv5te/OP_USHR_LONG.S */
   5039     /*
   5040      * Long integer shift.  This is different from the generic 32/64-bit
   5041      * binary operations because vAA/vBB are 64-bit but vCC (the shift
   5042      * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
   5043      * 6 bits of the shift distance.
   5044      */
   5045     /* ushr-long vAA, vBB, vCC */
   5046     FETCH(r0, 1)                        @ r0<- CCBB
   5047     mov     r9, rINST, lsr #8           @ r9<- AA
   5048     and     r3, r0, #255                @ r3<- BB
   5049     mov     r0, r0, lsr #8              @ r0<- CC
   5050     add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
   5051     GET_VREG(r2, r0)                    @ r2<- vCC
   5052     ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5053     and     r2, r2, #63                 @ r0<- r0 & 0x3f
   5054     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5055 
   5056     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   5057     rsb     r3, r2, #32                 @  r3<- 32 - r2
   5058     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   5059     subs    ip, r2, #32                 @  ip<- r2 - 32
   5060     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
   5061     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5062     b       .LOP_USHR_LONG_finish
   5063 
   5064 /* ------------------------------ */
   5065     .balign 64
   5066 .L_OP_ADD_FLOAT: /* 0xa6 */
   5067 /* File: armv5te/OP_ADD_FLOAT.S */
   5068 /* File: armv5te/binop.S */
   5069     /*
   5070      * Generic 32-bit binary operation.  Provide an "instr" line that
   5071      * specifies an instruction that performs "result = r0 op r1".
   5072      * This could be an ARM instruction or a function call.  (If the result
   5073      * comes back in a register other than r0, you can override "result".)
   5074      *
   5075      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5076      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5077      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5078      * handles it correctly.
   5079      *
   5080      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5081      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5082      *      mul-float, div-float, rem-float
   5083      */
   5084     /* binop vAA, vBB, vCC */
   5085     FETCH(r0, 1)                        @ r0<- CCBB
   5086     mov     r9, rINST, lsr #8           @ r9<- AA
   5087     mov     r3, r0, lsr #8              @ r3<- CC
   5088     and     r2, r0, #255                @ r2<- BB
   5089     GET_VREG(r1, r3)                    @ r1<- vCC
   5090     GET_VREG(r0, r2)                    @ r0<- vBB
   5091     .if 0
   5092     cmp     r1, #0                      @ is second operand zero?
   5093     beq     common_errDivideByZero
   5094     .endif
   5095 
   5096     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5097                                @ optional op; may set condition codes
   5098     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
   5099     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5100     SET_VREG(r0, r9)               @ vAA<- r0
   5101     GOTO_OPCODE(ip)                     @ jump to next instruction
   5102     /* 11-14 instructions */
   5103 
   5104 
   5105 /* ------------------------------ */
   5106     .balign 64
   5107 .L_OP_SUB_FLOAT: /* 0xa7 */
   5108 /* File: armv5te/OP_SUB_FLOAT.S */
   5109 /* File: armv5te/binop.S */
   5110     /*
   5111      * Generic 32-bit binary operation.  Provide an "instr" line that
   5112      * specifies an instruction that performs "result = r0 op r1".
   5113      * This could be an ARM instruction or a function call.  (If the result
   5114      * comes back in a register other than r0, you can override "result".)
   5115      *
   5116      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5117      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5118      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5119      * handles it correctly.
   5120      *
   5121      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5122      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5123      *      mul-float, div-float, rem-float
   5124      */
   5125     /* binop vAA, vBB, vCC */
   5126     FETCH(r0, 1)                        @ r0<- CCBB
   5127     mov     r9, rINST, lsr #8           @ r9<- AA
   5128     mov     r3, r0, lsr #8              @ r3<- CC
   5129     and     r2, r0, #255                @ r2<- BB
   5130     GET_VREG(r1, r3)                    @ r1<- vCC
   5131     GET_VREG(r0, r2)                    @ r0<- vBB
   5132     .if 0
   5133     cmp     r1, #0                      @ is second operand zero?
   5134     beq     common_errDivideByZero
   5135     .endif
   5136 
   5137     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5138                                @ optional op; may set condition codes
   5139     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
   5140     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5141     SET_VREG(r0, r9)               @ vAA<- r0
   5142     GOTO_OPCODE(ip)                     @ jump to next instruction
   5143     /* 11-14 instructions */
   5144 
   5145 
   5146 /* ------------------------------ */
   5147     .balign 64
   5148 .L_OP_MUL_FLOAT: /* 0xa8 */
   5149 /* File: armv5te/OP_MUL_FLOAT.S */
   5150 /* File: armv5te/binop.S */
   5151     /*
   5152      * Generic 32-bit binary operation.  Provide an "instr" line that
   5153      * specifies an instruction that performs "result = r0 op r1".
   5154      * This could be an ARM instruction or a function call.  (If the result
   5155      * comes back in a register other than r0, you can override "result".)
   5156      *
   5157      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5158      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5159      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5160      * handles it correctly.
   5161      *
   5162      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5163      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5164      *      mul-float, div-float, rem-float
   5165      */
   5166     /* binop vAA, vBB, vCC */
   5167     FETCH(r0, 1)                        @ r0<- CCBB
   5168     mov     r9, rINST, lsr #8           @ r9<- AA
   5169     mov     r3, r0, lsr #8              @ r3<- CC
   5170     and     r2, r0, #255                @ r2<- BB
   5171     GET_VREG(r1, r3)                    @ r1<- vCC
   5172     GET_VREG(r0, r2)                    @ r0<- vBB
   5173     .if 0
   5174     cmp     r1, #0                      @ is second operand zero?
   5175     beq     common_errDivideByZero
   5176     .endif
   5177 
   5178     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5179                                @ optional op; may set condition codes
   5180     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
   5181     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5182     SET_VREG(r0, r9)               @ vAA<- r0
   5183     GOTO_OPCODE(ip)                     @ jump to next instruction
   5184     /* 11-14 instructions */
   5185 
   5186 
   5187 /* ------------------------------ */
   5188     .balign 64
   5189 .L_OP_DIV_FLOAT: /* 0xa9 */
   5190 /* File: armv5te/OP_DIV_FLOAT.S */
   5191 /* File: armv5te/binop.S */
   5192     /*
   5193      * Generic 32-bit binary operation.  Provide an "instr" line that
   5194      * specifies an instruction that performs "result = r0 op r1".
   5195      * This could be an ARM instruction or a function call.  (If the result
   5196      * comes back in a register other than r0, you can override "result".)
   5197      *
   5198      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5199      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5200      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5201      * handles it correctly.
   5202      *
   5203      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5204      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5205      *      mul-float, div-float, rem-float
   5206      */
   5207     /* binop vAA, vBB, vCC */
   5208     FETCH(r0, 1)                        @ r0<- CCBB
   5209     mov     r9, rINST, lsr #8           @ r9<- AA
   5210     mov     r3, r0, lsr #8              @ r3<- CC
   5211     and     r2, r0, #255                @ r2<- BB
   5212     GET_VREG(r1, r3)                    @ r1<- vCC
   5213     GET_VREG(r0, r2)                    @ r0<- vBB
   5214     .if 0
   5215     cmp     r1, #0                      @ is second operand zero?
   5216     beq     common_errDivideByZero
   5217     .endif
   5218 
   5219     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5220                                @ optional op; may set condition codes
   5221     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
   5222     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5223     SET_VREG(r0, r9)               @ vAA<- r0
   5224     GOTO_OPCODE(ip)                     @ jump to next instruction
   5225     /* 11-14 instructions */
   5226 
   5227 
   5228 /* ------------------------------ */
   5229     .balign 64
   5230 .L_OP_REM_FLOAT: /* 0xaa */
   5231 /* File: armv5te/OP_REM_FLOAT.S */
   5232 /* EABI doesn't define a float remainder function, but libm does */
   5233 /* File: armv5te/binop.S */
   5234     /*
   5235      * Generic 32-bit binary operation.  Provide an "instr" line that
   5236      * specifies an instruction that performs "result = r0 op r1".
   5237      * This could be an ARM instruction or a function call.  (If the result
   5238      * comes back in a register other than r0, you can override "result".)
   5239      *
   5240      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5241      * vCC (r1).  Useful for integer division and modulus.  Note that we
   5242      * *don't* check for (INT_MIN / -1) here, because the ARM math lib
   5243      * handles it correctly.
   5244      *
   5245      * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
   5246      *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
   5247      *      mul-float, div-float, rem-float
   5248      */
   5249     /* binop vAA, vBB, vCC */
   5250     FETCH(r0, 1)                        @ r0<- CCBB
   5251     mov     r9, rINST, lsr #8           @ r9<- AA
   5252     mov     r3, r0, lsr #8              @ r3<- CC
   5253     and     r2, r0, #255                @ r2<- BB
   5254     GET_VREG(r1, r3)                    @ r1<- vCC
   5255     GET_VREG(r0, r2)                    @ r0<- vBB
   5256     .if 0
   5257     cmp     r1, #0                      @ is second operand zero?
   5258     beq     common_errDivideByZero
   5259     .endif
   5260 
   5261     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5262                                @ optional op; may set condition codes
   5263     bl      fmodf                              @ r0<- op, r0-r3 changed
   5264     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5265     SET_VREG(r0, r9)               @ vAA<- r0
   5266     GOTO_OPCODE(ip)                     @ jump to next instruction
   5267     /* 11-14 instructions */
   5268 
   5269 
   5270 /* ------------------------------ */
   5271     .balign 64
   5272 .L_OP_ADD_DOUBLE: /* 0xab */
   5273 /* File: armv5te/OP_ADD_DOUBLE.S */
   5274 /* File: armv5te/binopWide.S */
   5275     /*
   5276      * Generic 64-bit binary operation.  Provide an "instr" line that
   5277      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5278      * This could be an ARM instruction or a function call.  (If the result
   5279      * comes back in a register other than r0, you can override "result".)
   5280      *
   5281      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5282      * vCC (r1).  Useful for integer division and modulus.
   5283      *
   5284      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5285      *      xor-long, add-double, sub-double, mul-double, div-double,
   5286      *      rem-double
   5287      *
   5288      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5289      */
   5290     /* binop vAA, vBB, vCC */
   5291     FETCH(r0, 1)                        @ r0<- CCBB
   5292     mov     r9, rINST, lsr #8           @ r9<- AA
   5293     and     r2, r0, #255                @ r2<- BB
   5294     mov     r3, r0, lsr #8              @ r3<- CC
   5295     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5296     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5297     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5298     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5299     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5300     .if 0
   5301     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5302     beq     common_errDivideByZero
   5303     .endif
   5304     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5305 
   5306                                @ optional op; may set condition codes
   5307     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
   5308     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5309     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5310     GOTO_OPCODE(ip)                     @ jump to next instruction
   5311     /* 14-17 instructions */
   5312 
   5313 
   5314 /* ------------------------------ */
   5315     .balign 64
   5316 .L_OP_SUB_DOUBLE: /* 0xac */
   5317 /* File: armv5te/OP_SUB_DOUBLE.S */
   5318 /* File: armv5te/binopWide.S */
   5319     /*
   5320      * Generic 64-bit binary operation.  Provide an "instr" line that
   5321      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5322      * This could be an ARM instruction or a function call.  (If the result
   5323      * comes back in a register other than r0, you can override "result".)
   5324      *
   5325      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5326      * vCC (r1).  Useful for integer division and modulus.
   5327      *
   5328      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5329      *      xor-long, add-double, sub-double, mul-double, div-double,
   5330      *      rem-double
   5331      *
   5332      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5333      */
   5334     /* binop vAA, vBB, vCC */
   5335     FETCH(r0, 1)                        @ r0<- CCBB
   5336     mov     r9, rINST, lsr #8           @ r9<- AA
   5337     and     r2, r0, #255                @ r2<- BB
   5338     mov     r3, r0, lsr #8              @ r3<- CC
   5339     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5340     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5341     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5342     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5343     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5344     .if 0
   5345     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5346     beq     common_errDivideByZero
   5347     .endif
   5348     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5349 
   5350                                @ optional op; may set condition codes
   5351     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
   5352     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5353     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5354     GOTO_OPCODE(ip)                     @ jump to next instruction
   5355     /* 14-17 instructions */
   5356 
   5357 
   5358 /* ------------------------------ */
   5359     .balign 64
   5360 .L_OP_MUL_DOUBLE: /* 0xad */
   5361 /* File: armv5te/OP_MUL_DOUBLE.S */
   5362 /* File: armv5te/binopWide.S */
   5363     /*
   5364      * Generic 64-bit binary operation.  Provide an "instr" line that
   5365      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5366      * This could be an ARM instruction or a function call.  (If the result
   5367      * comes back in a register other than r0, you can override "result".)
   5368      *
   5369      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5370      * vCC (r1).  Useful for integer division and modulus.
   5371      *
   5372      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5373      *      xor-long, add-double, sub-double, mul-double, div-double,
   5374      *      rem-double
   5375      *
   5376      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5377      */
   5378     /* binop vAA, vBB, vCC */
   5379     FETCH(r0, 1)                        @ r0<- CCBB
   5380     mov     r9, rINST, lsr #8           @ r9<- AA
   5381     and     r2, r0, #255                @ r2<- BB
   5382     mov     r3, r0, lsr #8              @ r3<- CC
   5383     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5384     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5385     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5386     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5387     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5388     .if 0
   5389     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5390     beq     common_errDivideByZero
   5391     .endif
   5392     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5393 
   5394                                @ optional op; may set condition codes
   5395     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
   5396     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5397     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5398     GOTO_OPCODE(ip)                     @ jump to next instruction
   5399     /* 14-17 instructions */
   5400 
   5401 
   5402 /* ------------------------------ */
   5403     .balign 64
   5404 .L_OP_DIV_DOUBLE: /* 0xae */
   5405 /* File: armv5te/OP_DIV_DOUBLE.S */
   5406 /* File: armv5te/binopWide.S */
   5407     /*
   5408      * Generic 64-bit binary operation.  Provide an "instr" line that
   5409      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5410      * This could be an ARM instruction or a function call.  (If the result
   5411      * comes back in a register other than r0, you can override "result".)
   5412      *
   5413      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5414      * vCC (r1).  Useful for integer division and modulus.
   5415      *
   5416      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5417      *      xor-long, add-double, sub-double, mul-double, div-double,
   5418      *      rem-double
   5419      *
   5420      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5421      */
   5422     /* binop vAA, vBB, vCC */
   5423     FETCH(r0, 1)                        @ r0<- CCBB
   5424     mov     r9, rINST, lsr #8           @ r9<- AA
   5425     and     r2, r0, #255                @ r2<- BB
   5426     mov     r3, r0, lsr #8              @ r3<- CC
   5427     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5428     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5429     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5430     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5431     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5432     .if 0
   5433     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5434     beq     common_errDivideByZero
   5435     .endif
   5436     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5437 
   5438                                @ optional op; may set condition codes
   5439     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
   5440     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5441     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5442     GOTO_OPCODE(ip)                     @ jump to next instruction
   5443     /* 14-17 instructions */
   5444 
   5445 
   5446 /* ------------------------------ */
   5447     .balign 64
   5448 .L_OP_REM_DOUBLE: /* 0xaf */
   5449 /* File: armv5te/OP_REM_DOUBLE.S */
   5450 /* EABI doesn't define a double remainder function, but libm does */
   5451 /* File: armv5te/binopWide.S */
   5452     /*
   5453      * Generic 64-bit binary operation.  Provide an "instr" line that
   5454      * specifies an instruction that performs "result = r0-r1 op r2-r3".
   5455      * This could be an ARM instruction or a function call.  (If the result
   5456      * comes back in a register other than r0, you can override "result".)
   5457      *
   5458      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5459      * vCC (r1).  Useful for integer division and modulus.
   5460      *
   5461      * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
   5462      *      xor-long, add-double, sub-double, mul-double, div-double,
   5463      *      rem-double
   5464      *
   5465      * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
   5466      */
   5467     /* binop vAA, vBB, vCC */
   5468     FETCH(r0, 1)                        @ r0<- CCBB
   5469     mov     r9, rINST, lsr #8           @ r9<- AA
   5470     and     r2, r0, #255                @ r2<- BB
   5471     mov     r3, r0, lsr #8              @ r3<- CC
   5472     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   5473     add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
   5474     add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
   5475     ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
   5476     ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
   5477     .if 0
   5478     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5479     beq     common_errDivideByZero
   5480     .endif
   5481     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   5482 
   5483                                @ optional op; may set condition codes
   5484     bl      fmod                              @ result<- op, r0-r3 changed
   5485     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5486     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5487     GOTO_OPCODE(ip)                     @ jump to next instruction
   5488     /* 14-17 instructions */
   5489 
   5490 
   5491 /* ------------------------------ */
   5492     .balign 64
   5493 .L_OP_ADD_INT_2ADDR: /* 0xb0 */
   5494 /* File: armv5te/OP_ADD_INT_2ADDR.S */
   5495 /* File: armv5te/binop2addr.S */
   5496     /*
   5497      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5498      * that specifies an instruction that performs "result = r0 op r1".
   5499      * This could be an ARM instruction or a function call.  (If the result
   5500      * comes back in a register other than r0, you can override "result".)
   5501      *
   5502      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5503      * vCC (r1).  Useful for integer division and modulus.
   5504      *
   5505      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5506      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5507      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5508      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5509      */
   5510     /* binop/2addr vA, vB */
   5511     mov     r9, rINST, lsr #8           @ r9<- A+
   5512     mov     r3, rINST, lsr #12          @ r3<- B
   5513     and     r9, r9, #15
   5514     GET_VREG(r1, r3)                    @ r1<- vB
   5515     GET_VREG(r0, r9)                    @ r0<- vA
   5516     .if 0
   5517     cmp     r1, #0                      @ is second operand zero?
   5518     beq     common_errDivideByZero
   5519     .endif
   5520     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5521 
   5522                                @ optional op; may set condition codes
   5523     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5524     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5525     SET_VREG(r0, r9)               @ vAA<- r0
   5526     GOTO_OPCODE(ip)                     @ jump to next instruction
   5527     /* 10-13 instructions */
   5528 
   5529 
   5530 /* ------------------------------ */
   5531     .balign 64
   5532 .L_OP_SUB_INT_2ADDR: /* 0xb1 */
   5533 /* File: armv5te/OP_SUB_INT_2ADDR.S */
   5534 /* File: armv5te/binop2addr.S */
   5535     /*
   5536      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5537      * that specifies an instruction that performs "result = r0 op r1".
   5538      * This could be an ARM instruction or a function call.  (If the result
   5539      * comes back in a register other than r0, you can override "result".)
   5540      *
   5541      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5542      * vCC (r1).  Useful for integer division and modulus.
   5543      *
   5544      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5545      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5546      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5547      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5548      */
   5549     /* binop/2addr vA, vB */
   5550     mov     r9, rINST, lsr #8           @ r9<- A+
   5551     mov     r3, rINST, lsr #12          @ r3<- B
   5552     and     r9, r9, #15
   5553     GET_VREG(r1, r3)                    @ r1<- vB
   5554     GET_VREG(r0, r9)                    @ r0<- vA
   5555     .if 0
   5556     cmp     r1, #0                      @ is second operand zero?
   5557     beq     common_errDivideByZero
   5558     .endif
   5559     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5560 
   5561                                @ optional op; may set condition codes
   5562     sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5563     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5564     SET_VREG(r0, r9)               @ vAA<- r0
   5565     GOTO_OPCODE(ip)                     @ jump to next instruction
   5566     /* 10-13 instructions */
   5567 
   5568 
   5569 /* ------------------------------ */
   5570     .balign 64
   5571 .L_OP_MUL_INT_2ADDR: /* 0xb2 */
   5572 /* File: armv5te/OP_MUL_INT_2ADDR.S */
   5573 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   5574 /* File: armv5te/binop2addr.S */
   5575     /*
   5576      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5577      * that specifies an instruction that performs "result = r0 op r1".
   5578      * This could be an ARM instruction or a function call.  (If the result
   5579      * comes back in a register other than r0, you can override "result".)
   5580      *
   5581      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5582      * vCC (r1).  Useful for integer division and modulus.
   5583      *
   5584      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5585      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5586      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5587      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5588      */
   5589     /* binop/2addr vA, vB */
   5590     mov     r9, rINST, lsr #8           @ r9<- A+
   5591     mov     r3, rINST, lsr #12          @ r3<- B
   5592     and     r9, r9, #15
   5593     GET_VREG(r1, r3)                    @ r1<- vB
   5594     GET_VREG(r0, r9)                    @ r0<- vA
   5595     .if 0
   5596     cmp     r1, #0                      @ is second operand zero?
   5597     beq     common_errDivideByZero
   5598     .endif
   5599     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5600 
   5601                                @ optional op; may set condition codes
   5602     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   5603     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5604     SET_VREG(r0, r9)               @ vAA<- r0
   5605     GOTO_OPCODE(ip)                     @ jump to next instruction
   5606     /* 10-13 instructions */
   5607 
   5608 
   5609 /* ------------------------------ */
   5610     .balign 64
   5611 .L_OP_DIV_INT_2ADDR: /* 0xb3 */
   5612 /* File: armv5te/OP_DIV_INT_2ADDR.S */
   5613 /* File: armv5te/binop2addr.S */
   5614     /*
   5615      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5616      * that specifies an instruction that performs "result = r0 op r1".
   5617      * This could be an ARM instruction or a function call.  (If the result
   5618      * comes back in a register other than r0, you can override "result".)
   5619      *
   5620      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5621      * vCC (r1).  Useful for integer division and modulus.
   5622      *
   5623      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5624      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5625      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5626      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5627      */
   5628     /* binop/2addr vA, vB */
   5629     mov     r9, rINST, lsr #8           @ r9<- A+
   5630     mov     r3, rINST, lsr #12          @ r3<- B
   5631     and     r9, r9, #15
   5632     GET_VREG(r1, r3)                    @ r1<- vB
   5633     GET_VREG(r0, r9)                    @ r0<- vA
   5634     .if 1
   5635     cmp     r1, #0                      @ is second operand zero?
   5636     beq     common_errDivideByZero
   5637     .endif
   5638     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5639 
   5640                                @ optional op; may set condition codes
   5641     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   5642     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5643     SET_VREG(r0, r9)               @ vAA<- r0
   5644     GOTO_OPCODE(ip)                     @ jump to next instruction
   5645     /* 10-13 instructions */
   5646 
   5647 
   5648 /* ------------------------------ */
   5649     .balign 64
   5650 .L_OP_REM_INT_2ADDR: /* 0xb4 */
   5651 /* File: armv5te/OP_REM_INT_2ADDR.S */
   5652 /* idivmod returns quotient in r0 and remainder in r1 */
   5653 /* File: armv5te/binop2addr.S */
   5654     /*
   5655      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5656      * that specifies an instruction that performs "result = r0 op r1".
   5657      * This could be an ARM instruction or a function call.  (If the result
   5658      * comes back in a register other than r0, you can override "result".)
   5659      *
   5660      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5661      * vCC (r1).  Useful for integer division and modulus.
   5662      *
   5663      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5664      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5665      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5666      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5667      */
   5668     /* binop/2addr vA, vB */
   5669     mov     r9, rINST, lsr #8           @ r9<- A+
   5670     mov     r3, rINST, lsr #12          @ r3<- B
   5671     and     r9, r9, #15
   5672     GET_VREG(r1, r3)                    @ r1<- vB
   5673     GET_VREG(r0, r9)                    @ r0<- vA
   5674     .if 1
   5675     cmp     r1, #0                      @ is second operand zero?
   5676     beq     common_errDivideByZero
   5677     .endif
   5678     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5679 
   5680                                @ optional op; may set condition codes
   5681     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   5682     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5683     SET_VREG(r1, r9)               @ vAA<- r1
   5684     GOTO_OPCODE(ip)                     @ jump to next instruction
   5685     /* 10-13 instructions */
   5686 
   5687 
   5688 /* ------------------------------ */
   5689     .balign 64
   5690 .L_OP_AND_INT_2ADDR: /* 0xb5 */
   5691 /* File: armv5te/OP_AND_INT_2ADDR.S */
   5692 /* File: armv5te/binop2addr.S */
   5693     /*
   5694      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5695      * that specifies an instruction that performs "result = r0 op r1".
   5696      * This could be an ARM instruction or a function call.  (If the result
   5697      * comes back in a register other than r0, you can override "result".)
   5698      *
   5699      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5700      * vCC (r1).  Useful for integer division and modulus.
   5701      *
   5702      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5703      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5704      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5705      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5706      */
   5707     /* binop/2addr vA, vB */
   5708     mov     r9, rINST, lsr #8           @ r9<- A+
   5709     mov     r3, rINST, lsr #12          @ r3<- B
   5710     and     r9, r9, #15
   5711     GET_VREG(r1, r3)                    @ r1<- vB
   5712     GET_VREG(r0, r9)                    @ r0<- vA
   5713     .if 0
   5714     cmp     r1, #0                      @ is second operand zero?
   5715     beq     common_errDivideByZero
   5716     .endif
   5717     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5718 
   5719                                @ optional op; may set condition codes
   5720     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5721     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5722     SET_VREG(r0, r9)               @ vAA<- r0
   5723     GOTO_OPCODE(ip)                     @ jump to next instruction
   5724     /* 10-13 instructions */
   5725 
   5726 
   5727 /* ------------------------------ */
   5728     .balign 64
   5729 .L_OP_OR_INT_2ADDR: /* 0xb6 */
   5730 /* File: armv5te/OP_OR_INT_2ADDR.S */
   5731 /* File: armv5te/binop2addr.S */
   5732     /*
   5733      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5734      * that specifies an instruction that performs "result = r0 op r1".
   5735      * This could be an ARM instruction or a function call.  (If the result
   5736      * comes back in a register other than r0, you can override "result".)
   5737      *
   5738      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5739      * vCC (r1).  Useful for integer division and modulus.
   5740      *
   5741      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5742      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5743      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5744      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5745      */
   5746     /* binop/2addr vA, vB */
   5747     mov     r9, rINST, lsr #8           @ r9<- A+
   5748     mov     r3, rINST, lsr #12          @ r3<- B
   5749     and     r9, r9, #15
   5750     GET_VREG(r1, r3)                    @ r1<- vB
   5751     GET_VREG(r0, r9)                    @ r0<- vA
   5752     .if 0
   5753     cmp     r1, #0                      @ is second operand zero?
   5754     beq     common_errDivideByZero
   5755     .endif
   5756     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5757 
   5758                                @ optional op; may set condition codes
   5759     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5760     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5761     SET_VREG(r0, r9)               @ vAA<- r0
   5762     GOTO_OPCODE(ip)                     @ jump to next instruction
   5763     /* 10-13 instructions */
   5764 
   5765 
   5766 /* ------------------------------ */
   5767     .balign 64
   5768 .L_OP_XOR_INT_2ADDR: /* 0xb7 */
   5769 /* File: armv5te/OP_XOR_INT_2ADDR.S */
   5770 /* File: armv5te/binop2addr.S */
   5771     /*
   5772      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5773      * that specifies an instruction that performs "result = r0 op r1".
   5774      * This could be an ARM instruction or a function call.  (If the result
   5775      * comes back in a register other than r0, you can override "result".)
   5776      *
   5777      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5778      * vCC (r1).  Useful for integer division and modulus.
   5779      *
   5780      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5781      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5782      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5783      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5784      */
   5785     /* binop/2addr vA, vB */
   5786     mov     r9, rINST, lsr #8           @ r9<- A+
   5787     mov     r3, rINST, lsr #12          @ r3<- B
   5788     and     r9, r9, #15
   5789     GET_VREG(r1, r3)                    @ r1<- vB
   5790     GET_VREG(r0, r9)                    @ r0<- vA
   5791     .if 0
   5792     cmp     r1, #0                      @ is second operand zero?
   5793     beq     common_errDivideByZero
   5794     .endif
   5795     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5796 
   5797                                @ optional op; may set condition codes
   5798     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   5799     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5800     SET_VREG(r0, r9)               @ vAA<- r0
   5801     GOTO_OPCODE(ip)                     @ jump to next instruction
   5802     /* 10-13 instructions */
   5803 
   5804 
   5805 /* ------------------------------ */
   5806     .balign 64
   5807 .L_OP_SHL_INT_2ADDR: /* 0xb8 */
   5808 /* File: armv5te/OP_SHL_INT_2ADDR.S */
   5809 /* File: armv5te/binop2addr.S */
   5810     /*
   5811      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5812      * that specifies an instruction that performs "result = r0 op r1".
   5813      * This could be an ARM instruction or a function call.  (If the result
   5814      * comes back in a register other than r0, you can override "result".)
   5815      *
   5816      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5817      * vCC (r1).  Useful for integer division and modulus.
   5818      *
   5819      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5820      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5821      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5822      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5823      */
   5824     /* binop/2addr vA, vB */
   5825     mov     r9, rINST, lsr #8           @ r9<- A+
   5826     mov     r3, rINST, lsr #12          @ r3<- B
   5827     and     r9, r9, #15
   5828     GET_VREG(r1, r3)                    @ r1<- vB
   5829     GET_VREG(r0, r9)                    @ r0<- vA
   5830     .if 0
   5831     cmp     r1, #0                      @ is second operand zero?
   5832     beq     common_errDivideByZero
   5833     .endif
   5834     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5835 
   5836     and     r1, r1, #31                           @ optional op; may set condition codes
   5837     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   5838     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5839     SET_VREG(r0, r9)               @ vAA<- r0
   5840     GOTO_OPCODE(ip)                     @ jump to next instruction
   5841     /* 10-13 instructions */
   5842 
   5843 
   5844 /* ------------------------------ */
   5845     .balign 64
   5846 .L_OP_SHR_INT_2ADDR: /* 0xb9 */
   5847 /* File: armv5te/OP_SHR_INT_2ADDR.S */
   5848 /* File: armv5te/binop2addr.S */
   5849     /*
   5850      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5851      * that specifies an instruction that performs "result = r0 op r1".
   5852      * This could be an ARM instruction or a function call.  (If the result
   5853      * comes back in a register other than r0, you can override "result".)
   5854      *
   5855      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5856      * vCC (r1).  Useful for integer division and modulus.
   5857      *
   5858      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5859      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5860      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5861      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5862      */
   5863     /* binop/2addr vA, vB */
   5864     mov     r9, rINST, lsr #8           @ r9<- A+
   5865     mov     r3, rINST, lsr #12          @ r3<- B
   5866     and     r9, r9, #15
   5867     GET_VREG(r1, r3)                    @ r1<- vB
   5868     GET_VREG(r0, r9)                    @ r0<- vA
   5869     .if 0
   5870     cmp     r1, #0                      @ is second operand zero?
   5871     beq     common_errDivideByZero
   5872     .endif
   5873     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5874 
   5875     and     r1, r1, #31                           @ optional op; may set condition codes
   5876     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   5877     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5878     SET_VREG(r0, r9)               @ vAA<- r0
   5879     GOTO_OPCODE(ip)                     @ jump to next instruction
   5880     /* 10-13 instructions */
   5881 
   5882 
   5883 /* ------------------------------ */
   5884     .balign 64
   5885 .L_OP_USHR_INT_2ADDR: /* 0xba */
   5886 /* File: armv5te/OP_USHR_INT_2ADDR.S */
   5887 /* File: armv5te/binop2addr.S */
   5888     /*
   5889      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   5890      * that specifies an instruction that performs "result = r0 op r1".
   5891      * This could be an ARM instruction or a function call.  (If the result
   5892      * comes back in a register other than r0, you can override "result".)
   5893      *
   5894      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5895      * vCC (r1).  Useful for integer division and modulus.
   5896      *
   5897      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   5898      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   5899      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   5900      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   5901      */
   5902     /* binop/2addr vA, vB */
   5903     mov     r9, rINST, lsr #8           @ r9<- A+
   5904     mov     r3, rINST, lsr #12          @ r3<- B
   5905     and     r9, r9, #15
   5906     GET_VREG(r1, r3)                    @ r1<- vB
   5907     GET_VREG(r0, r9)                    @ r0<- vA
   5908     .if 0
   5909     cmp     r1, #0                      @ is second operand zero?
   5910     beq     common_errDivideByZero
   5911     .endif
   5912     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5913 
   5914     and     r1, r1, #31                           @ optional op; may set condition codes
   5915     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   5916     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5917     SET_VREG(r0, r9)               @ vAA<- r0
   5918     GOTO_OPCODE(ip)                     @ jump to next instruction
   5919     /* 10-13 instructions */
   5920 
   5921 
   5922 /* ------------------------------ */
   5923     .balign 64
   5924 .L_OP_ADD_LONG_2ADDR: /* 0xbb */
   5925 /* File: armv5te/OP_ADD_LONG_2ADDR.S */
   5926 /* File: armv5te/binopWide2addr.S */
   5927     /*
   5928      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5929      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5930      * This could be an ARM instruction or a function call.  (If the result
   5931      * comes back in a register other than r0, you can override "result".)
   5932      *
   5933      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5934      * vCC (r1).  Useful for integer division and modulus.
   5935      *
   5936      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5937      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5938      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5939      *      rem-double/2addr
   5940      */
   5941     /* binop/2addr vA, vB */
   5942     mov     r9, rINST, lsr #8           @ r9<- A+
   5943     mov     r1, rINST, lsr #12          @ r1<- B
   5944     and     r9, r9, #15
   5945     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5946     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5947     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5948     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5949     .if 0
   5950     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5951     beq     common_errDivideByZero
   5952     .endif
   5953     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5954 
   5955     adds    r0, r0, r2                           @ optional op; may set condition codes
   5956     adc     r1, r1, r3                              @ result<- op, r0-r3 changed
   5957     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5958     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   5959     GOTO_OPCODE(ip)                     @ jump to next instruction
   5960     /* 12-15 instructions */
   5961 
   5962 
   5963 /* ------------------------------ */
   5964     .balign 64
   5965 .L_OP_SUB_LONG_2ADDR: /* 0xbc */
   5966 /* File: armv5te/OP_SUB_LONG_2ADDR.S */
   5967 /* File: armv5te/binopWide2addr.S */
   5968     /*
   5969      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   5970      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   5971      * This could be an ARM instruction or a function call.  (If the result
   5972      * comes back in a register other than r0, you can override "result".)
   5973      *
   5974      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   5975      * vCC (r1).  Useful for integer division and modulus.
   5976      *
   5977      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   5978      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   5979      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   5980      *      rem-double/2addr
   5981      */
   5982     /* binop/2addr vA, vB */
   5983     mov     r9, rINST, lsr #8           @ r9<- A+
   5984     mov     r1, rINST, lsr #12          @ r1<- B
   5985     and     r9, r9, #15
   5986     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   5987     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   5988     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   5989     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   5990     .if 0
   5991     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   5992     beq     common_errDivideByZero
   5993     .endif
   5994     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   5995 
   5996     subs    r0, r0, r2                           @ optional op; may set condition codes
   5997     sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
   5998     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   5999     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6000     GOTO_OPCODE(ip)                     @ jump to next instruction
   6001     /* 12-15 instructions */
   6002 
   6003 
   6004 /* ------------------------------ */
   6005     .balign 64
   6006 .L_OP_MUL_LONG_2ADDR: /* 0xbd */
   6007 /* File: armv5te/OP_MUL_LONG_2ADDR.S */
   6008     /*
   6009      * Signed 64-bit integer multiply, "/2addr" version.
   6010      *
   6011      * See OP_MUL_LONG for an explanation.
   6012      *
   6013      * We get a little tight on registers, so to avoid looking up &fp[A]
   6014      * again we stuff it into rINST.
   6015      */
   6016     /* mul-long/2addr vA, vB */
   6017     mov     r9, rINST, lsr #8           @ r9<- A+
   6018     mov     r1, rINST, lsr #12          @ r1<- B
   6019     and     r9, r9, #15
   6020     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6021     add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
   6022     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6023     ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
   6024     mul     ip, r2, r1                  @  ip<- ZxW
   6025     umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
   6026     mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
   6027     mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
   6028     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6029     add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
   6030     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6031     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
   6032     GOTO_OPCODE(ip)                     @ jump to next instruction
   6033 
   6034 /* ------------------------------ */
   6035     .balign 64
   6036 .L_OP_DIV_LONG_2ADDR: /* 0xbe */
   6037 /* File: armv5te/OP_DIV_LONG_2ADDR.S */
   6038 /* File: armv5te/binopWide2addr.S */
   6039     /*
   6040      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6041      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6042      * This could be an ARM instruction or a function call.  (If the result
   6043      * comes back in a register other than r0, you can override "result".)
   6044      *
   6045      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6046      * vCC (r1).  Useful for integer division and modulus.
   6047      *
   6048      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6049      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6050      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6051      *      rem-double/2addr
   6052      */
   6053     /* binop/2addr vA, vB */
   6054     mov     r9, rINST, lsr #8           @ r9<- A+
   6055     mov     r1, rINST, lsr #12          @ r1<- B
   6056     and     r9, r9, #15
   6057     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6058     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6059     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6060     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6061     .if 1
   6062     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6063     beq     common_errDivideByZero
   6064     .endif
   6065     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6066 
   6067                                @ optional op; may set condition codes
   6068     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   6069     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6070     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6071     GOTO_OPCODE(ip)                     @ jump to next instruction
   6072     /* 12-15 instructions */
   6073 
   6074 
   6075 /* ------------------------------ */
   6076     .balign 64
   6077 .L_OP_REM_LONG_2ADDR: /* 0xbf */
   6078 /* File: armv5te/OP_REM_LONG_2ADDR.S */
   6079 /* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
   6080 /* File: armv5te/binopWide2addr.S */
   6081     /*
   6082      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6083      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6084      * This could be an ARM instruction or a function call.  (If the result
   6085      * comes back in a register other than r0, you can override "result".)
   6086      *
   6087      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6088      * vCC (r1).  Useful for integer division and modulus.
   6089      *
   6090      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6091      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6092      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6093      *      rem-double/2addr
   6094      */
   6095     /* binop/2addr vA, vB */
   6096     mov     r9, rINST, lsr #8           @ r9<- A+
   6097     mov     r1, rINST, lsr #12          @ r1<- B
   6098     and     r9, r9, #15
   6099     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6100     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6101     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6102     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6103     .if 1
   6104     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6105     beq     common_errDivideByZero
   6106     .endif
   6107     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6108 
   6109                                @ optional op; may set condition codes
   6110     bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
   6111     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6112     stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
   6113     GOTO_OPCODE(ip)                     @ jump to next instruction
   6114     /* 12-15 instructions */
   6115 
   6116 
   6117 /* ------------------------------ */
   6118     .balign 64
   6119 .L_OP_AND_LONG_2ADDR: /* 0xc0 */
   6120 /* File: armv5te/OP_AND_LONG_2ADDR.S */
   6121 /* File: armv5te/binopWide2addr.S */
   6122     /*
   6123      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6124      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6125      * This could be an ARM instruction or a function call.  (If the result
   6126      * comes back in a register other than r0, you can override "result".)
   6127      *
   6128      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6129      * vCC (r1).  Useful for integer division and modulus.
   6130      *
   6131      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6132      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6133      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6134      *      rem-double/2addr
   6135      */
   6136     /* binop/2addr vA, vB */
   6137     mov     r9, rINST, lsr #8           @ r9<- A+
   6138     mov     r1, rINST, lsr #12          @ r1<- B
   6139     and     r9, r9, #15
   6140     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6141     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6142     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6143     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6144     .if 0
   6145     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6146     beq     common_errDivideByZero
   6147     .endif
   6148     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6149 
   6150     and     r0, r0, r2                           @ optional op; may set condition codes
   6151     and     r1, r1, r3                              @ result<- op, r0-r3 changed
   6152     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6153     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6154     GOTO_OPCODE(ip)                     @ jump to next instruction
   6155     /* 12-15 instructions */
   6156 
   6157 
   6158 /* ------------------------------ */
   6159     .balign 64
   6160 .L_OP_OR_LONG_2ADDR: /* 0xc1 */
   6161 /* File: armv5te/OP_OR_LONG_2ADDR.S */
   6162 /* File: armv5te/binopWide2addr.S */
   6163     /*
   6164      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6165      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6166      * This could be an ARM instruction or a function call.  (If the result
   6167      * comes back in a register other than r0, you can override "result".)
   6168      *
   6169      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6170      * vCC (r1).  Useful for integer division and modulus.
   6171      *
   6172      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6173      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6174      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6175      *      rem-double/2addr
   6176      */
   6177     /* binop/2addr vA, vB */
   6178     mov     r9, rINST, lsr #8           @ r9<- A+
   6179     mov     r1, rINST, lsr #12          @ r1<- B
   6180     and     r9, r9, #15
   6181     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6182     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6183     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6184     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6185     .if 0
   6186     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6187     beq     common_errDivideByZero
   6188     .endif
   6189     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6190 
   6191     orr     r0, r0, r2                           @ optional op; may set condition codes
   6192     orr     r1, r1, r3                              @ result<- op, r0-r3 changed
   6193     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6194     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6195     GOTO_OPCODE(ip)                     @ jump to next instruction
   6196     /* 12-15 instructions */
   6197 
   6198 
   6199 /* ------------------------------ */
   6200     .balign 64
   6201 .L_OP_XOR_LONG_2ADDR: /* 0xc2 */
   6202 /* File: armv5te/OP_XOR_LONG_2ADDR.S */
   6203 /* File: armv5te/binopWide2addr.S */
   6204     /*
   6205      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6206      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6207      * This could be an ARM instruction or a function call.  (If the result
   6208      * comes back in a register other than r0, you can override "result".)
   6209      *
   6210      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6211      * vCC (r1).  Useful for integer division and modulus.
   6212      *
   6213      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6214      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6215      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6216      *      rem-double/2addr
   6217      */
   6218     /* binop/2addr vA, vB */
   6219     mov     r9, rINST, lsr #8           @ r9<- A+
   6220     mov     r1, rINST, lsr #12          @ r1<- B
   6221     and     r9, r9, #15
   6222     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6223     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6224     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6225     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6226     .if 0
   6227     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6228     beq     common_errDivideByZero
   6229     .endif
   6230     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6231 
   6232     eor     r0, r0, r2                           @ optional op; may set condition codes
   6233     eor     r1, r1, r3                              @ result<- op, r0-r3 changed
   6234     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6235     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6236     GOTO_OPCODE(ip)                     @ jump to next instruction
   6237     /* 12-15 instructions */
   6238 
   6239 
   6240 /* ------------------------------ */
   6241     .balign 64
   6242 .L_OP_SHL_LONG_2ADDR: /* 0xc3 */
   6243 /* File: armv5te/OP_SHL_LONG_2ADDR.S */
   6244     /*
   6245      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6246      * 32-bit shift distance.
   6247      */
   6248     /* shl-long/2addr vA, vB */
   6249     mov     r9, rINST, lsr #8           @ r9<- A+
   6250     mov     r3, rINST, lsr #12          @ r3<- B
   6251     and     r9, r9, #15
   6252     GET_VREG(r2, r3)                    @ r2<- vB
   6253     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6254     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6255     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6256 
   6257     mov     r1, r1, asl r2              @  r1<- r1 << r2
   6258     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6259     orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
   6260     subs    ip, r2, #32                 @  ip<- r2 - 32
   6261     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6262     movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
   6263     mov     r0, r0, asl r2              @  r0<- r0 << r2
   6264     b       .LOP_SHL_LONG_2ADDR_finish
   6265 
   6266 /* ------------------------------ */
   6267     .balign 64
   6268 .L_OP_SHR_LONG_2ADDR: /* 0xc4 */
   6269 /* File: armv5te/OP_SHR_LONG_2ADDR.S */
   6270     /*
   6271      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6272      * 32-bit shift distance.
   6273      */
   6274     /* shr-long/2addr vA, vB */
   6275     mov     r9, rINST, lsr #8           @ r9<- A+
   6276     mov     r3, rINST, lsr #12          @ r3<- B
   6277     and     r9, r9, #15
   6278     GET_VREG(r2, r3)                    @ r2<- vB
   6279     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6280     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6281     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6282 
   6283     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   6284     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6285     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   6286     subs    ip, r2, #32                 @  ip<- r2 - 32
   6287     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6288     movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
   6289     mov     r1, r1, asr r2              @  r1<- r1 >> r2
   6290     b       .LOP_SHR_LONG_2ADDR_finish
   6291 
   6292 /* ------------------------------ */
   6293     .balign 64
   6294 .L_OP_USHR_LONG_2ADDR: /* 0xc5 */
   6295 /* File: armv5te/OP_USHR_LONG_2ADDR.S */
   6296     /*
   6297      * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
   6298      * 32-bit shift distance.
   6299      */
   6300     /* ushr-long/2addr vA, vB */
   6301     mov     r9, rINST, lsr #8           @ r9<- A+
   6302     mov     r3, rINST, lsr #12          @ r3<- B
   6303     and     r9, r9, #15
   6304     GET_VREG(r2, r3)                    @ r2<- vB
   6305     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6306     and     r2, r2, #63                 @ r2<- r2 & 0x3f
   6307     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6308 
   6309     mov     r0, r0, lsr r2              @  r0<- r2 >> r2
   6310     rsb     r3, r2, #32                 @  r3<- 32 - r2
   6311     orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
   6312     subs    ip, r2, #32                 @  ip<- r2 - 32
   6313     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6314     movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
   6315     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
   6316     b       .LOP_USHR_LONG_2ADDR_finish
   6317 
   6318 /* ------------------------------ */
   6319     .balign 64
   6320 .L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
   6321 /* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
   6322 /* File: armv5te/binop2addr.S */
   6323     /*
   6324      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6325      * that specifies an instruction that performs "result = r0 op r1".
   6326      * This could be an ARM instruction or a function call.  (If the result
   6327      * comes back in a register other than r0, you can override "result".)
   6328      *
   6329      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6330      * vCC (r1).  Useful for integer division and modulus.
   6331      *
   6332      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6333      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6334      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6335      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6336      */
   6337     /* binop/2addr vA, vB */
   6338     mov     r9, rINST, lsr #8           @ r9<- A+
   6339     mov     r3, rINST, lsr #12          @ r3<- B
   6340     and     r9, r9, #15
   6341     GET_VREG(r1, r3)                    @ r1<- vB
   6342     GET_VREG(r0, r9)                    @ r0<- vA
   6343     .if 0
   6344     cmp     r1, #0                      @ is second operand zero?
   6345     beq     common_errDivideByZero
   6346     .endif
   6347     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6348 
   6349                                @ optional op; may set condition codes
   6350     bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
   6351     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6352     SET_VREG(r0, r9)               @ vAA<- r0
   6353     GOTO_OPCODE(ip)                     @ jump to next instruction
   6354     /* 10-13 instructions */
   6355 
   6356 
   6357 /* ------------------------------ */
   6358     .balign 64
   6359 .L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
   6360 /* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
   6361 /* File: armv5te/binop2addr.S */
   6362     /*
   6363      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6364      * that specifies an instruction that performs "result = r0 op r1".
   6365      * This could be an ARM instruction or a function call.  (If the result
   6366      * comes back in a register other than r0, you can override "result".)
   6367      *
   6368      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6369      * vCC (r1).  Useful for integer division and modulus.
   6370      *
   6371      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6372      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6373      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6374      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6375      */
   6376     /* binop/2addr vA, vB */
   6377     mov     r9, rINST, lsr #8           @ r9<- A+
   6378     mov     r3, rINST, lsr #12          @ r3<- B
   6379     and     r9, r9, #15
   6380     GET_VREG(r1, r3)                    @ r1<- vB
   6381     GET_VREG(r0, r9)                    @ r0<- vA
   6382     .if 0
   6383     cmp     r1, #0                      @ is second operand zero?
   6384     beq     common_errDivideByZero
   6385     .endif
   6386     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6387 
   6388                                @ optional op; may set condition codes
   6389     bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
   6390     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6391     SET_VREG(r0, r9)               @ vAA<- r0
   6392     GOTO_OPCODE(ip)                     @ jump to next instruction
   6393     /* 10-13 instructions */
   6394 
   6395 
   6396 /* ------------------------------ */
   6397     .balign 64
   6398 .L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
   6399 /* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
   6400 /* File: armv5te/binop2addr.S */
   6401     /*
   6402      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6403      * that specifies an instruction that performs "result = r0 op r1".
   6404      * This could be an ARM instruction or a function call.  (If the result
   6405      * comes back in a register other than r0, you can override "result".)
   6406      *
   6407      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6408      * vCC (r1).  Useful for integer division and modulus.
   6409      *
   6410      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6411      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6412      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6413      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6414      */
   6415     /* binop/2addr vA, vB */
   6416     mov     r9, rINST, lsr #8           @ r9<- A+
   6417     mov     r3, rINST, lsr #12          @ r3<- B
   6418     and     r9, r9, #15
   6419     GET_VREG(r1, r3)                    @ r1<- vB
   6420     GET_VREG(r0, r9)                    @ r0<- vA
   6421     .if 0
   6422     cmp     r1, #0                      @ is second operand zero?
   6423     beq     common_errDivideByZero
   6424     .endif
   6425     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6426 
   6427                                @ optional op; may set condition codes
   6428     bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
   6429     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6430     SET_VREG(r0, r9)               @ vAA<- r0
   6431     GOTO_OPCODE(ip)                     @ jump to next instruction
   6432     /* 10-13 instructions */
   6433 
   6434 
   6435 /* ------------------------------ */
   6436     .balign 64
   6437 .L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
   6438 /* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
   6439 /* File: armv5te/binop2addr.S */
   6440     /*
   6441      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6442      * that specifies an instruction that performs "result = r0 op r1".
   6443      * This could be an ARM instruction or a function call.  (If the result
   6444      * comes back in a register other than r0, you can override "result".)
   6445      *
   6446      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6447      * vCC (r1).  Useful for integer division and modulus.
   6448      *
   6449      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6450      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6451      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6452      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6453      */
   6454     /* binop/2addr vA, vB */
   6455     mov     r9, rINST, lsr #8           @ r9<- A+
   6456     mov     r3, rINST, lsr #12          @ r3<- B
   6457     and     r9, r9, #15
   6458     GET_VREG(r1, r3)                    @ r1<- vB
   6459     GET_VREG(r0, r9)                    @ r0<- vA
   6460     .if 0
   6461     cmp     r1, #0                      @ is second operand zero?
   6462     beq     common_errDivideByZero
   6463     .endif
   6464     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6465 
   6466                                @ optional op; may set condition codes
   6467     bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
   6468     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6469     SET_VREG(r0, r9)               @ vAA<- r0
   6470     GOTO_OPCODE(ip)                     @ jump to next instruction
   6471     /* 10-13 instructions */
   6472 
   6473 
   6474 /* ------------------------------ */
   6475     .balign 64
   6476 .L_OP_REM_FLOAT_2ADDR: /* 0xca */
   6477 /* File: armv5te/OP_REM_FLOAT_2ADDR.S */
   6478 /* EABI doesn't define a float remainder function, but libm does */
   6479 /* File: armv5te/binop2addr.S */
   6480     /*
   6481      * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
   6482      * that specifies an instruction that performs "result = r0 op r1".
   6483      * This could be an ARM instruction or a function call.  (If the result
   6484      * comes back in a register other than r0, you can override "result".)
   6485      *
   6486      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6487      * vCC (r1).  Useful for integer division and modulus.
   6488      *
   6489      * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
   6490      *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
   6491      *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
   6492      *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
   6493      */
   6494     /* binop/2addr vA, vB */
   6495     mov     r9, rINST, lsr #8           @ r9<- A+
   6496     mov     r3, rINST, lsr #12          @ r3<- B
   6497     and     r9, r9, #15
   6498     GET_VREG(r1, r3)                    @ r1<- vB
   6499     GET_VREG(r0, r9)                    @ r0<- vA
   6500     .if 0
   6501     cmp     r1, #0                      @ is second operand zero?
   6502     beq     common_errDivideByZero
   6503     .endif
   6504     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6505 
   6506                                @ optional op; may set condition codes
   6507     bl      fmodf                              @ r0<- op, r0-r3 changed
   6508     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6509     SET_VREG(r0, r9)               @ vAA<- r0
   6510     GOTO_OPCODE(ip)                     @ jump to next instruction
   6511     /* 10-13 instructions */
   6512 
   6513 
   6514 /* ------------------------------ */
   6515     .balign 64
   6516 .L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
   6517 /* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
   6518 /* File: armv5te/binopWide2addr.S */
   6519     /*
   6520      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6521      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6522      * This could be an ARM instruction or a function call.  (If the result
   6523      * comes back in a register other than r0, you can override "result".)
   6524      *
   6525      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6526      * vCC (r1).  Useful for integer division and modulus.
   6527      *
   6528      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6529      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6530      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6531      *      rem-double/2addr
   6532      */
   6533     /* binop/2addr vA, vB */
   6534     mov     r9, rINST, lsr #8           @ r9<- A+
   6535     mov     r1, rINST, lsr #12          @ r1<- B
   6536     and     r9, r9, #15
   6537     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6538     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6539     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6540     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6541     .if 0
   6542     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6543     beq     common_errDivideByZero
   6544     .endif
   6545     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6546 
   6547                                @ optional op; may set condition codes
   6548     bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
   6549     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6550     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6551     GOTO_OPCODE(ip)                     @ jump to next instruction
   6552     /* 12-15 instructions */
   6553 
   6554 
   6555 /* ------------------------------ */
   6556     .balign 64
   6557 .L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
   6558 /* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
   6559 /* File: armv5te/binopWide2addr.S */
   6560     /*
   6561      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6562      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6563      * This could be an ARM instruction or a function call.  (If the result
   6564      * comes back in a register other than r0, you can override "result".)
   6565      *
   6566      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6567      * vCC (r1).  Useful for integer division and modulus.
   6568      *
   6569      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6570      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6571      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6572      *      rem-double/2addr
   6573      */
   6574     /* binop/2addr vA, vB */
   6575     mov     r9, rINST, lsr #8           @ r9<- A+
   6576     mov     r1, rINST, lsr #12          @ r1<- B
   6577     and     r9, r9, #15
   6578     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6579     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6580     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6581     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6582     .if 0
   6583     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6584     beq     common_errDivideByZero
   6585     .endif
   6586     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6587 
   6588                                @ optional op; may set condition codes
   6589     bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
   6590     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6591     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6592     GOTO_OPCODE(ip)                     @ jump to next instruction
   6593     /* 12-15 instructions */
   6594 
   6595 
   6596 /* ------------------------------ */
   6597     .balign 64
   6598 .L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
   6599 /* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
   6600 /* File: armv5te/binopWide2addr.S */
   6601     /*
   6602      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6603      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6604      * This could be an ARM instruction or a function call.  (If the result
   6605      * comes back in a register other than r0, you can override "result".)
   6606      *
   6607      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6608      * vCC (r1).  Useful for integer division and modulus.
   6609      *
   6610      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6611      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6612      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6613      *      rem-double/2addr
   6614      */
   6615     /* binop/2addr vA, vB */
   6616     mov     r9, rINST, lsr #8           @ r9<- A+
   6617     mov     r1, rINST, lsr #12          @ r1<- B
   6618     and     r9, r9, #15
   6619     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6620     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6621     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6622     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6623     .if 0
   6624     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6625     beq     common_errDivideByZero
   6626     .endif
   6627     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6628 
   6629                                @ optional op; may set condition codes
   6630     bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
   6631     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6632     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6633     GOTO_OPCODE(ip)                     @ jump to next instruction
   6634     /* 12-15 instructions */
   6635 
   6636 
   6637 /* ------------------------------ */
   6638     .balign 64
   6639 .L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
   6640 /* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
   6641 /* File: armv5te/binopWide2addr.S */
   6642     /*
   6643      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6644      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6645      * This could be an ARM instruction or a function call.  (If the result
   6646      * comes back in a register other than r0, you can override "result".)
   6647      *
   6648      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6649      * vCC (r1).  Useful for integer division and modulus.
   6650      *
   6651      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6652      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6653      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6654      *      rem-double/2addr
   6655      */
   6656     /* binop/2addr vA, vB */
   6657     mov     r9, rINST, lsr #8           @ r9<- A+
   6658     mov     r1, rINST, lsr #12          @ r1<- B
   6659     and     r9, r9, #15
   6660     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6661     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6662     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6663     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6664     .if 0
   6665     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6666     beq     common_errDivideByZero
   6667     .endif
   6668     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6669 
   6670                                @ optional op; may set condition codes
   6671     bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
   6672     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6673     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6674     GOTO_OPCODE(ip)                     @ jump to next instruction
   6675     /* 12-15 instructions */
   6676 
   6677 
   6678 /* ------------------------------ */
   6679     .balign 64
   6680 .L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
   6681 /* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
   6682 /* EABI doesn't define a double remainder function, but libm does */
   6683 /* File: armv5te/binopWide2addr.S */
   6684     /*
   6685      * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
   6686      * that specifies an instruction that performs "result = r0-r1 op r2-r3".
   6687      * This could be an ARM instruction or a function call.  (If the result
   6688      * comes back in a register other than r0, you can override "result".)
   6689      *
   6690      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6691      * vCC (r1).  Useful for integer division and modulus.
   6692      *
   6693      * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
   6694      *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
   6695      *      sub-double/2addr, mul-double/2addr, div-double/2addr,
   6696      *      rem-double/2addr
   6697      */
   6698     /* binop/2addr vA, vB */
   6699     mov     r9, rINST, lsr #8           @ r9<- A+
   6700     mov     r1, rINST, lsr #12          @ r1<- B
   6701     and     r9, r9, #15
   6702     add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
   6703     add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
   6704     ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
   6705     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   6706     .if 0
   6707     orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
   6708     beq     common_errDivideByZero
   6709     .endif
   6710     FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
   6711 
   6712                                @ optional op; may set condition codes
   6713     bl      fmod                              @ result<- op, r0-r3 changed
   6714     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6715     stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
   6716     GOTO_OPCODE(ip)                     @ jump to next instruction
   6717     /* 12-15 instructions */
   6718 
   6719 
   6720 /* ------------------------------ */
   6721     .balign 64
   6722 .L_OP_ADD_INT_LIT16: /* 0xd0 */
   6723 /* File: armv5te/OP_ADD_INT_LIT16.S */
   6724 /* File: armv5te/binopLit16.S */
   6725     /*
   6726      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6727      * that specifies an instruction that performs "result = r0 op r1".
   6728      * This could be an ARM instruction or a function call.  (If the result
   6729      * comes back in a register other than r0, you can override "result".)
   6730      *
   6731      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6732      * vCC (r1).  Useful for integer division and modulus.
   6733      *
   6734      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6735      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6736      */
   6737     /* binop/lit16 vA, vB, #+CCCC */
   6738     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6739     mov     r2, rINST, lsr #12          @ r2<- B
   6740     mov     r9, rINST, lsr #8           @ r9<- A+
   6741     GET_VREG(r0, r2)                    @ r0<- vB
   6742     and     r9, r9, #15
   6743     .if 0
   6744     cmp     r1, #0                      @ is second operand zero?
   6745     beq     common_errDivideByZero
   6746     .endif
   6747     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6748 
   6749     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6750     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6751     SET_VREG(r0, r9)               @ vAA<- r0
   6752     GOTO_OPCODE(ip)                     @ jump to next instruction
   6753     /* 10-13 instructions */
   6754 
   6755 
   6756 /* ------------------------------ */
   6757     .balign 64
   6758 .L_OP_RSUB_INT: /* 0xd1 */
   6759 /* File: armv5te/OP_RSUB_INT.S */
   6760 /* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
   6761 /* File: armv5te/binopLit16.S */
   6762     /*
   6763      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6764      * that specifies an instruction that performs "result = r0 op r1".
   6765      * This could be an ARM instruction or a function call.  (If the result
   6766      * comes back in a register other than r0, you can override "result".)
   6767      *
   6768      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6769      * vCC (r1).  Useful for integer division and modulus.
   6770      *
   6771      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6772      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6773      */
   6774     /* binop/lit16 vA, vB, #+CCCC */
   6775     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6776     mov     r2, rINST, lsr #12          @ r2<- B
   6777     mov     r9, rINST, lsr #8           @ r9<- A+
   6778     GET_VREG(r0, r2)                    @ r0<- vB
   6779     and     r9, r9, #15
   6780     .if 0
   6781     cmp     r1, #0                      @ is second operand zero?
   6782     beq     common_errDivideByZero
   6783     .endif
   6784     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6785 
   6786     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6787     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6788     SET_VREG(r0, r9)               @ vAA<- r0
   6789     GOTO_OPCODE(ip)                     @ jump to next instruction
   6790     /* 10-13 instructions */
   6791 
   6792 
   6793 /* ------------------------------ */
   6794     .balign 64
   6795 .L_OP_MUL_INT_LIT16: /* 0xd2 */
   6796 /* File: armv5te/OP_MUL_INT_LIT16.S */
   6797 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   6798 /* File: armv5te/binopLit16.S */
   6799     /*
   6800      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6801      * that specifies an instruction that performs "result = r0 op r1".
   6802      * This could be an ARM instruction or a function call.  (If the result
   6803      * comes back in a register other than r0, you can override "result".)
   6804      *
   6805      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6806      * vCC (r1).  Useful for integer division and modulus.
   6807      *
   6808      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6809      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6810      */
   6811     /* binop/lit16 vA, vB, #+CCCC */
   6812     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6813     mov     r2, rINST, lsr #12          @ r2<- B
   6814     mov     r9, rINST, lsr #8           @ r9<- A+
   6815     GET_VREG(r0, r2)                    @ r0<- vB
   6816     and     r9, r9, #15
   6817     .if 0
   6818     cmp     r1, #0                      @ is second operand zero?
   6819     beq     common_errDivideByZero
   6820     .endif
   6821     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6822 
   6823     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   6824     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6825     SET_VREG(r0, r9)               @ vAA<- r0
   6826     GOTO_OPCODE(ip)                     @ jump to next instruction
   6827     /* 10-13 instructions */
   6828 
   6829 
   6830 /* ------------------------------ */
   6831     .balign 64
   6832 .L_OP_DIV_INT_LIT16: /* 0xd3 */
   6833 /* File: armv5te/OP_DIV_INT_LIT16.S */
   6834 /* File: armv5te/binopLit16.S */
   6835     /*
   6836      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6837      * that specifies an instruction that performs "result = r0 op r1".
   6838      * This could be an ARM instruction or a function call.  (If the result
   6839      * comes back in a register other than r0, you can override "result".)
   6840      *
   6841      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6842      * vCC (r1).  Useful for integer division and modulus.
   6843      *
   6844      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6845      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6846      */
   6847     /* binop/lit16 vA, vB, #+CCCC */
   6848     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6849     mov     r2, rINST, lsr #12          @ r2<- B
   6850     mov     r9, rINST, lsr #8           @ r9<- A+
   6851     GET_VREG(r0, r2)                    @ r0<- vB
   6852     and     r9, r9, #15
   6853     .if 1
   6854     cmp     r1, #0                      @ is second operand zero?
   6855     beq     common_errDivideByZero
   6856     .endif
   6857     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6858 
   6859     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   6860     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6861     SET_VREG(r0, r9)               @ vAA<- r0
   6862     GOTO_OPCODE(ip)                     @ jump to next instruction
   6863     /* 10-13 instructions */
   6864 
   6865 
   6866 /* ------------------------------ */
   6867     .balign 64
   6868 .L_OP_REM_INT_LIT16: /* 0xd4 */
   6869 /* File: armv5te/OP_REM_INT_LIT16.S */
   6870 /* idivmod returns quotient in r0 and remainder in r1 */
   6871 /* File: armv5te/binopLit16.S */
   6872     /*
   6873      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6874      * that specifies an instruction that performs "result = r0 op r1".
   6875      * This could be an ARM instruction or a function call.  (If the result
   6876      * comes back in a register other than r0, you can override "result".)
   6877      *
   6878      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6879      * vCC (r1).  Useful for integer division and modulus.
   6880      *
   6881      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6882      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6883      */
   6884     /* binop/lit16 vA, vB, #+CCCC */
   6885     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6886     mov     r2, rINST, lsr #12          @ r2<- B
   6887     mov     r9, rINST, lsr #8           @ r9<- A+
   6888     GET_VREG(r0, r2)                    @ r0<- vB
   6889     and     r9, r9, #15
   6890     .if 1
   6891     cmp     r1, #0                      @ is second operand zero?
   6892     beq     common_errDivideByZero
   6893     .endif
   6894     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6895 
   6896     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   6897     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6898     SET_VREG(r1, r9)               @ vAA<- r1
   6899     GOTO_OPCODE(ip)                     @ jump to next instruction
   6900     /* 10-13 instructions */
   6901 
   6902 
   6903 /* ------------------------------ */
   6904     .balign 64
   6905 .L_OP_AND_INT_LIT16: /* 0xd5 */
   6906 /* File: armv5te/OP_AND_INT_LIT16.S */
   6907 /* File: armv5te/binopLit16.S */
   6908     /*
   6909      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6910      * that specifies an instruction that performs "result = r0 op r1".
   6911      * This could be an ARM instruction or a function call.  (If the result
   6912      * comes back in a register other than r0, you can override "result".)
   6913      *
   6914      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6915      * vCC (r1).  Useful for integer division and modulus.
   6916      *
   6917      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6918      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6919      */
   6920     /* binop/lit16 vA, vB, #+CCCC */
   6921     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6922     mov     r2, rINST, lsr #12          @ r2<- B
   6923     mov     r9, rINST, lsr #8           @ r9<- A+
   6924     GET_VREG(r0, r2)                    @ r0<- vB
   6925     and     r9, r9, #15
   6926     .if 0
   6927     cmp     r1, #0                      @ is second operand zero?
   6928     beq     common_errDivideByZero
   6929     .endif
   6930     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6931 
   6932     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6933     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6934     SET_VREG(r0, r9)               @ vAA<- r0
   6935     GOTO_OPCODE(ip)                     @ jump to next instruction
   6936     /* 10-13 instructions */
   6937 
   6938 
   6939 /* ------------------------------ */
   6940     .balign 64
   6941 .L_OP_OR_INT_LIT16: /* 0xd6 */
   6942 /* File: armv5te/OP_OR_INT_LIT16.S */
   6943 /* File: armv5te/binopLit16.S */
   6944     /*
   6945      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6946      * that specifies an instruction that performs "result = r0 op r1".
   6947      * This could be an ARM instruction or a function call.  (If the result
   6948      * comes back in a register other than r0, you can override "result".)
   6949      *
   6950      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6951      * vCC (r1).  Useful for integer division and modulus.
   6952      *
   6953      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6954      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6955      */
   6956     /* binop/lit16 vA, vB, #+CCCC */
   6957     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6958     mov     r2, rINST, lsr #12          @ r2<- B
   6959     mov     r9, rINST, lsr #8           @ r9<- A+
   6960     GET_VREG(r0, r2)                    @ r0<- vB
   6961     and     r9, r9, #15
   6962     .if 0
   6963     cmp     r1, #0                      @ is second operand zero?
   6964     beq     common_errDivideByZero
   6965     .endif
   6966     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   6967 
   6968     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   6969     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   6970     SET_VREG(r0, r9)               @ vAA<- r0
   6971     GOTO_OPCODE(ip)                     @ jump to next instruction
   6972     /* 10-13 instructions */
   6973 
   6974 
   6975 /* ------------------------------ */
   6976     .balign 64
   6977 .L_OP_XOR_INT_LIT16: /* 0xd7 */
   6978 /* File: armv5te/OP_XOR_INT_LIT16.S */
   6979 /* File: armv5te/binopLit16.S */
   6980     /*
   6981      * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
   6982      * that specifies an instruction that performs "result = r0 op r1".
   6983      * This could be an ARM instruction or a function call.  (If the result
   6984      * comes back in a register other than r0, you can override "result".)
   6985      *
   6986      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   6987      * vCC (r1).  Useful for integer division and modulus.
   6988      *
   6989      * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
   6990      *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
   6991      */
   6992     /* binop/lit16 vA, vB, #+CCCC */
   6993     FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
   6994     mov     r2, rINST, lsr #12          @ r2<- B
   6995     mov     r9, rINST, lsr #8           @ r9<- A+
   6996     GET_VREG(r0, r2)                    @ r0<- vB
   6997     and     r9, r9, #15
   6998     .if 0
   6999     cmp     r1, #0                      @ is second operand zero?
   7000     beq     common_errDivideByZero
   7001     .endif
   7002     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7003 
   7004     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   7005     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7006     SET_VREG(r0, r9)               @ vAA<- r0
   7007     GOTO_OPCODE(ip)                     @ jump to next instruction
   7008     /* 10-13 instructions */
   7009 
   7010 
   7011 /* ------------------------------ */
   7012     .balign 64
   7013 .L_OP_ADD_INT_LIT8: /* 0xd8 */
   7014 /* File: armv5te/OP_ADD_INT_LIT8.S */
   7015 /* File: armv5te/binopLit8.S */
   7016     /*
   7017      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7018      * that specifies an instruction that performs "result = r0 op r1".
   7019      * This could be an ARM instruction or a function call.  (If the result
   7020      * comes back in a register other than r0, you can override "result".)
   7021      *
   7022      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7023      * vCC (r1).  Useful for integer division and modulus.
   7024      *
   7025      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7026      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7027      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7028      */
   7029     /* binop/lit8 vAA, vBB, #+CC */
   7030     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7031     mov     r9, rINST, lsr #8           @ r9<- AA
   7032     and     r2, r3, #255                @ r2<- BB
   7033     GET_VREG(r0, r2)                    @ r0<- vBB
   7034     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7035     .if 0
   7036     @cmp     r1, #0                      @ is second operand zero?
   7037     beq     common_errDivideByZero
   7038     .endif
   7039     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7040 
   7041                                @ optional op; may set condition codes
   7042     add     r0, r0, r1                              @ r0<- op, r0-r3 changed
   7043     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7044     SET_VREG(r0, r9)               @ vAA<- r0
   7045     GOTO_OPCODE(ip)                     @ jump to next instruction
   7046     /* 10-12 instructions */
   7047 
   7048 
   7049 /* ------------------------------ */
   7050     .balign 64
   7051 .L_OP_RSUB_INT_LIT8: /* 0xd9 */
   7052 /* File: armv5te/OP_RSUB_INT_LIT8.S */
   7053 /* File: armv5te/binopLit8.S */
   7054     /*
   7055      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7056      * that specifies an instruction that performs "result = r0 op r1".
   7057      * This could be an ARM instruction or a function call.  (If the result
   7058      * comes back in a register other than r0, you can override "result".)
   7059      *
   7060      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7061      * vCC (r1).  Useful for integer division and modulus.
   7062      *
   7063      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7064      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7065      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7066      */
   7067     /* binop/lit8 vAA, vBB, #+CC */
   7068     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7069     mov     r9, rINST, lsr #8           @ r9<- AA
   7070     and     r2, r3, #255                @ r2<- BB
   7071     GET_VREG(r0, r2)                    @ r0<- vBB
   7072     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7073     .if 0
   7074     @cmp     r1, #0                      @ is second operand zero?
   7075     beq     common_errDivideByZero
   7076     .endif
   7077     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7078 
   7079                                @ optional op; may set condition codes
   7080     rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
   7081     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7082     SET_VREG(r0, r9)               @ vAA<- r0
   7083     GOTO_OPCODE(ip)                     @ jump to next instruction
   7084     /* 10-12 instructions */
   7085 
   7086 
   7087 /* ------------------------------ */
   7088     .balign 64
   7089 .L_OP_MUL_INT_LIT8: /* 0xda */
   7090 /* File: armv5te/OP_MUL_INT_LIT8.S */
   7091 /* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
   7092 /* File: armv5te/binopLit8.S */
   7093     /*
   7094      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7095      * that specifies an instruction that performs "result = r0 op r1".
   7096      * This could be an ARM instruction or a function call.  (If the result
   7097      * comes back in a register other than r0, you can override "result".)
   7098      *
   7099      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7100      * vCC (r1).  Useful for integer division and modulus.
   7101      *
   7102      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7103      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7104      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7105      */
   7106     /* binop/lit8 vAA, vBB, #+CC */
   7107     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7108     mov     r9, rINST, lsr #8           @ r9<- AA
   7109     and     r2, r3, #255                @ r2<- BB
   7110     GET_VREG(r0, r2)                    @ r0<- vBB
   7111     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7112     .if 0
   7113     @cmp     r1, #0                      @ is second operand zero?
   7114     beq     common_errDivideByZero
   7115     .endif
   7116     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7117 
   7118                                @ optional op; may set condition codes
   7119     mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
   7120     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7121     SET_VREG(r0, r9)               @ vAA<- r0
   7122     GOTO_OPCODE(ip)                     @ jump to next instruction
   7123     /* 10-12 instructions */
   7124 
   7125 
   7126 /* ------------------------------ */
   7127     .balign 64
   7128 .L_OP_DIV_INT_LIT8: /* 0xdb */
   7129 /* File: armv5te/OP_DIV_INT_LIT8.S */
   7130 /* File: armv5te/binopLit8.S */
   7131     /*
   7132      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7133      * that specifies an instruction that performs "result = r0 op r1".
   7134      * This could be an ARM instruction or a function call.  (If the result
   7135      * comes back in a register other than r0, you can override "result".)
   7136      *
   7137      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7138      * vCC (r1).  Useful for integer division and modulus.
   7139      *
   7140      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7141      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7142      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7143      */
   7144     /* binop/lit8 vAA, vBB, #+CC */
   7145     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7146     mov     r9, rINST, lsr #8           @ r9<- AA
   7147     and     r2, r3, #255                @ r2<- BB
   7148     GET_VREG(r0, r2)                    @ r0<- vBB
   7149     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7150     .if 1
   7151     @cmp     r1, #0                      @ is second operand zero?
   7152     beq     common_errDivideByZero
   7153     .endif
   7154     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7155 
   7156                                @ optional op; may set condition codes
   7157     bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
   7158     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7159     SET_VREG(r0, r9)               @ vAA<- r0
   7160     GOTO_OPCODE(ip)                     @ jump to next instruction
   7161     /* 10-12 instructions */
   7162 
   7163 
   7164 /* ------------------------------ */
   7165     .balign 64
   7166 .L_OP_REM_INT_LIT8: /* 0xdc */
   7167 /* File: armv5te/OP_REM_INT_LIT8.S */
   7168 /* idivmod returns quotient in r0 and remainder in r1 */
   7169 /* File: armv5te/binopLit8.S */
   7170     /*
   7171      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7172      * that specifies an instruction that performs "result = r0 op r1".
   7173      * This could be an ARM instruction or a function call.  (If the result
   7174      * comes back in a register other than r0, you can override "result".)
   7175      *
   7176      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7177      * vCC (r1).  Useful for integer division and modulus.
   7178      *
   7179      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7180      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7181      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7182      */
   7183     /* binop/lit8 vAA, vBB, #+CC */
   7184     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7185     mov     r9, rINST, lsr #8           @ r9<- AA
   7186     and     r2, r3, #255                @ r2<- BB
   7187     GET_VREG(r0, r2)                    @ r0<- vBB
   7188     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7189     .if 1
   7190     @cmp     r1, #0                      @ is second operand zero?
   7191     beq     common_errDivideByZero
   7192     .endif
   7193     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7194 
   7195                                @ optional op; may set condition codes
   7196     bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
   7197     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7198     SET_VREG(r1, r9)               @ vAA<- r1
   7199     GOTO_OPCODE(ip)                     @ jump to next instruction
   7200     /* 10-12 instructions */
   7201 
   7202 
   7203 /* ------------------------------ */
   7204     .balign 64
   7205 .L_OP_AND_INT_LIT8: /* 0xdd */
   7206 /* File: armv5te/OP_AND_INT_LIT8.S */
   7207 /* File: armv5te/binopLit8.S */
   7208     /*
   7209      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7210      * that specifies an instruction that performs "result = r0 op r1".
   7211      * This could be an ARM instruction or a function call.  (If the result
   7212      * comes back in a register other than r0, you can override "result".)
   7213      *
   7214      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7215      * vCC (r1).  Useful for integer division and modulus.
   7216      *
   7217      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7218      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7219      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7220      */
   7221     /* binop/lit8 vAA, vBB, #+CC */
   7222     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7223     mov     r9, rINST, lsr #8           @ r9<- AA
   7224     and     r2, r3, #255                @ r2<- BB
   7225     GET_VREG(r0, r2)                    @ r0<- vBB
   7226     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7227     .if 0
   7228     @cmp     r1, #0                      @ is second operand zero?
   7229     beq     common_errDivideByZero
   7230     .endif
   7231     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7232 
   7233                                @ optional op; may set condition codes
   7234     and     r0, r0, r1                              @ r0<- op, r0-r3 changed
   7235     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7236     SET_VREG(r0, r9)               @ vAA<- r0
   7237     GOTO_OPCODE(ip)                     @ jump to next instruction
   7238     /* 10-12 instructions */
   7239 
   7240 
   7241 /* ------------------------------ */
   7242     .balign 64
   7243 .L_OP_OR_INT_LIT8: /* 0xde */
   7244 /* File: armv5te/OP_OR_INT_LIT8.S */
   7245 /* File: armv5te/binopLit8.S */
   7246     /*
   7247      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7248      * that specifies an instruction that performs "result = r0 op r1".
   7249      * This could be an ARM instruction or a function call.  (If the result
   7250      * comes back in a register other than r0, you can override "result".)
   7251      *
   7252      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7253      * vCC (r1).  Useful for integer division and modulus.
   7254      *
   7255      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7256      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7257      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7258      */
   7259     /* binop/lit8 vAA, vBB, #+CC */
   7260     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7261     mov     r9, rINST, lsr #8           @ r9<- AA
   7262     and     r2, r3, #255                @ r2<- BB
   7263     GET_VREG(r0, r2)                    @ r0<- vBB
   7264     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7265     .if 0
   7266     @cmp     r1, #0                      @ is second operand zero?
   7267     beq     common_errDivideByZero
   7268     .endif
   7269     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7270 
   7271                                @ optional op; may set condition codes
   7272     orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
   7273     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7274     SET_VREG(r0, r9)               @ vAA<- r0
   7275     GOTO_OPCODE(ip)                     @ jump to next instruction
   7276     /* 10-12 instructions */
   7277 
   7278 
   7279 /* ------------------------------ */
   7280     .balign 64
   7281 .L_OP_XOR_INT_LIT8: /* 0xdf */
   7282 /* File: armv5te/OP_XOR_INT_LIT8.S */
   7283 /* File: armv5te/binopLit8.S */
   7284     /*
   7285      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7286      * that specifies an instruction that performs "result = r0 op r1".
   7287      * This could be an ARM instruction or a function call.  (If the result
   7288      * comes back in a register other than r0, you can override "result".)
   7289      *
   7290      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7291      * vCC (r1).  Useful for integer division and modulus.
   7292      *
   7293      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7294      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7295      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7296      */
   7297     /* binop/lit8 vAA, vBB, #+CC */
   7298     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7299     mov     r9, rINST, lsr #8           @ r9<- AA
   7300     and     r2, r3, #255                @ r2<- BB
   7301     GET_VREG(r0, r2)                    @ r0<- vBB
   7302     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7303     .if 0
   7304     @cmp     r1, #0                      @ is second operand zero?
   7305     beq     common_errDivideByZero
   7306     .endif
   7307     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7308 
   7309                                @ optional op; may set condition codes
   7310     eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
   7311     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7312     SET_VREG(r0, r9)               @ vAA<- r0
   7313     GOTO_OPCODE(ip)                     @ jump to next instruction
   7314     /* 10-12 instructions */
   7315 
   7316 
   7317 /* ------------------------------ */
   7318     .balign 64
   7319 .L_OP_SHL_INT_LIT8: /* 0xe0 */
   7320 /* File: armv5te/OP_SHL_INT_LIT8.S */
   7321 /* File: armv5te/binopLit8.S */
   7322     /*
   7323      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7324      * that specifies an instruction that performs "result = r0 op r1".
   7325      * This could be an ARM instruction or a function call.  (If the result
   7326      * comes back in a register other than r0, you can override "result".)
   7327      *
   7328      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7329      * vCC (r1).  Useful for integer division and modulus.
   7330      *
   7331      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7332      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7333      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7334      */
   7335     /* binop/lit8 vAA, vBB, #+CC */
   7336     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7337     mov     r9, rINST, lsr #8           @ r9<- AA
   7338     and     r2, r3, #255                @ r2<- BB
   7339     GET_VREG(r0, r2)                    @ r0<- vBB
   7340     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7341     .if 0
   7342     @cmp     r1, #0                      @ is second operand zero?
   7343     beq     common_errDivideByZero
   7344     .endif
   7345     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7346 
   7347     and     r1, r1, #31                           @ optional op; may set condition codes
   7348     mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
   7349     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7350     SET_VREG(r0, r9)               @ vAA<- r0
   7351     GOTO_OPCODE(ip)                     @ jump to next instruction
   7352     /* 10-12 instructions */
   7353 
   7354 
   7355 /* ------------------------------ */
   7356     .balign 64
   7357 .L_OP_SHR_INT_LIT8: /* 0xe1 */
   7358 /* File: armv5te/OP_SHR_INT_LIT8.S */
   7359 /* File: armv5te/binopLit8.S */
   7360     /*
   7361      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7362      * that specifies an instruction that performs "result = r0 op r1".
   7363      * This could be an ARM instruction or a function call.  (If the result
   7364      * comes back in a register other than r0, you can override "result".)
   7365      *
   7366      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7367      * vCC (r1).  Useful for integer division and modulus.
   7368      *
   7369      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7370      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7371      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7372      */
   7373     /* binop/lit8 vAA, vBB, #+CC */
   7374     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7375     mov     r9, rINST, lsr #8           @ r9<- AA
   7376     and     r2, r3, #255                @ r2<- BB
   7377     GET_VREG(r0, r2)                    @ r0<- vBB
   7378     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7379     .if 0
   7380     @cmp     r1, #0                      @ is second operand zero?
   7381     beq     common_errDivideByZero
   7382     .endif
   7383     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7384 
   7385     and     r1, r1, #31                           @ optional op; may set condition codes
   7386     mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
   7387     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7388     SET_VREG(r0, r9)               @ vAA<- r0
   7389     GOTO_OPCODE(ip)                     @ jump to next instruction
   7390     /* 10-12 instructions */
   7391 
   7392 
   7393 /* ------------------------------ */
   7394     .balign 64
   7395 .L_OP_USHR_INT_LIT8: /* 0xe2 */
   7396 /* File: armv5te/OP_USHR_INT_LIT8.S */
   7397 /* File: armv5te/binopLit8.S */
   7398     /*
   7399      * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
   7400      * that specifies an instruction that performs "result = r0 op r1".
   7401      * This could be an ARM instruction or a function call.  (If the result
   7402      * comes back in a register other than r0, you can override "result".)
   7403      *
   7404      * If "chkzero" is set to 1, we perform a divide-by-zero check on
   7405      * vCC (r1).  Useful for integer division and modulus.
   7406      *
   7407      * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
   7408      *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
   7409      *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
   7410      */
   7411     /* binop/lit8 vAA, vBB, #+CC */
   7412     FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
   7413     mov     r9, rINST, lsr #8           @ r9<- AA
   7414     and     r2, r3, #255                @ r2<- BB
   7415     GET_VREG(r0, r2)                    @ r0<- vBB
   7416     movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
   7417     .if 0
   7418     @cmp     r1, #0                      @ is second operand zero?
   7419     beq     common_errDivideByZero
   7420     .endif
   7421     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7422 
   7423     and     r1, r1, #31                           @ optional op; may set condition codes
   7424     mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
   7425     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7426     SET_VREG(r0, r9)               @ vAA<- r0
   7427     GOTO_OPCODE(ip)                     @ jump to next instruction
   7428     /* 10-12 instructions */
   7429 
   7430 
   7431 /* ------------------------------ */
   7432     .balign 64
   7433 .L_OP_IGET_VOLATILE: /* 0xe3 */
   7434 /* File: armv5te/OP_IGET_VOLATILE.S */
   7435 /* File: armv5te/OP_IGET.S */
   7436     /*
   7437      * General 32-bit instance field get.
   7438      *
   7439      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   7440      */
   7441     /* op vA, vB, field@CCCC */
   7442     mov     r0, rINST, lsr #12          @ r0<- B
   7443     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7444     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7445     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7446     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7447     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7448     cmp     r0, #0                      @ is resolved entry null?
   7449     bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
   7450 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7451     EXPORT_PC()                         @ resolve() could throw
   7452     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7453     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7454     cmp     r0, #0
   7455     bne     .LOP_IGET_VOLATILE_finish
   7456     b       common_exceptionThrown
   7457 
   7458 
   7459 /* ------------------------------ */
   7460     .balign 64
   7461 .L_OP_IPUT_VOLATILE: /* 0xe4 */
   7462 /* File: armv5te/OP_IPUT_VOLATILE.S */
   7463 /* File: armv5te/OP_IPUT.S */
   7464     /*
   7465      * General 32-bit instance field put.
   7466      *
   7467      * for: iput, iput-boolean, iput-byte, iput-char, iput-short
   7468      */
   7469     /* op vA, vB, field@CCCC */
   7470     mov     r0, rINST, lsr #12          @ r0<- B
   7471     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7472     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7473     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7474     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7475     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7476     cmp     r0, #0                      @ is resolved entry null?
   7477     bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
   7478 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7479     EXPORT_PC()                         @ resolve() could throw
   7480     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7481     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7482     cmp     r0, #0                      @ success?
   7483     bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
   7484     b       common_exceptionThrown
   7485 
   7486 
   7487 /* ------------------------------ */
   7488     .balign 64
   7489 .L_OP_SGET_VOLATILE: /* 0xe5 */
   7490 /* File: armv5te/OP_SGET_VOLATILE.S */
   7491 /* File: armv5te/OP_SGET.S */
   7492     /*
   7493      * General 32-bit SGET handler.
   7494      *
   7495      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   7496      */
   7497     /* op vAA, field@BBBB */
   7498     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7499     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7500     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7501     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7502     cmp     r0, #0                      @ is resolved entry null?
   7503     beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
   7504 .LOP_SGET_VOLATILE_finish: @ field ptr in r0
   7505     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   7506     SMP_DMB                            @ acquiring load
   7507     mov     r2, rINST, lsr #8           @ r2<- AA
   7508     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7509     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   7510     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7511     GOTO_OPCODE(ip)                     @ jump to next instruction
   7512 
   7513 
   7514 /* ------------------------------ */
   7515     .balign 64
   7516 .L_OP_SPUT_VOLATILE: /* 0xe6 */
   7517 /* File: armv5te/OP_SPUT_VOLATILE.S */
   7518 /* File: armv5te/OP_SPUT.S */
   7519     /*
   7520      * General 32-bit SPUT handler.
   7521      *
   7522      * for: sput, sput-boolean, sput-byte, sput-char, sput-short
   7523      */
   7524     /* op vAA, field@BBBB */
   7525     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7526     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7527     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7528     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7529     cmp     r0, #0                      @ is resolved entry null?
   7530     beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
   7531 .LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
   7532     mov     r2, rINST, lsr #8           @ r2<- AA
   7533     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7534     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   7535     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7536     SMP_DMB                            @ releasing store
   7537     str     r1, [r0, #offStaticField_value] @ field<- vAA
   7538     GOTO_OPCODE(ip)                     @ jump to next instruction
   7539 
   7540 
   7541 /* ------------------------------ */
   7542     .balign 64
   7543 .L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
   7544 /* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
   7545 /* File: armv5te/OP_IGET.S */
   7546     /*
   7547      * General 32-bit instance field get.
   7548      *
   7549      * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
   7550      */
   7551     /* op vA, vB, field@CCCC */
   7552     mov     r0, rINST, lsr #12          @ r0<- B
   7553     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7554     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7555     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   7556     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7557     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7558     cmp     r0, #0                      @ is resolved entry null?
   7559     bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
   7560 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7561     EXPORT_PC()                         @ resolve() could throw
   7562     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7563     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7564     cmp     r0, #0
   7565     bne     .LOP_IGET_OBJECT_VOLATILE_finish
   7566     b       common_exceptionThrown
   7567 
   7568 
   7569 /* ------------------------------ */
   7570     .balign 64
   7571 .L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
   7572 /* File: armv4t/OP_IGET_WIDE_VOLATILE.S */
   7573 /* File: armv4t/OP_IGET_WIDE.S */
   7574     /*
   7575      * Wide 32-bit instance field get.
   7576      */
   7577     /* iget-wide vA, vB, field@CCCC */
   7578     mov     r0, rINST, lsr #12          @ r0<- B
   7579     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7580     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7581     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   7582     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7583     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7584     cmp     r0, #0                      @ is resolved entry null?
   7585     bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
   7586 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   7587     EXPORT_PC()                         @ resolve() could throw
   7588     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7589     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7590     cmp     r0, #0
   7591     bne     .LOP_IGET_WIDE_VOLATILE_finish
   7592     b       common_exceptionThrown
   7593 
   7594 
   7595 /* ------------------------------ */
   7596     .balign 64
   7597 .L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
   7598 /* File: armv4t/OP_IPUT_WIDE_VOLATILE.S */
   7599 /* File: armv4t/OP_IPUT_WIDE.S */
   7600     /* iput-wide vA, vB, field@CCCC */
   7601     mov     r0, rINST, lsr #12          @ r0<- B
   7602     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   7603     FETCH(r1, 1)                        @ r1<- field ref CCCC
   7604     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
   7605     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   7606     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   7607     cmp     r0, #0                      @ is resolved entry null?
   7608     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
   7609 8:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
   7610     EXPORT_PC()                         @ resolve() could throw
   7611     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   7612     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   7613     cmp     r0, #0                      @ success?
   7614     bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
   7615     b       common_exceptionThrown
   7616 
   7617 
   7618 /* ------------------------------ */
   7619     .balign 64
   7620 .L_OP_SGET_WIDE_VOLATILE: /* 0xea */
   7621 /* File: armv4t/OP_SGET_WIDE_VOLATILE.S */
   7622 /* File: armv4t/OP_SGET_WIDE.S */
   7623     /*
   7624      * 64-bit SGET handler.
   7625      */
   7626     /* sget-wide vAA, field@BBBB */
   7627     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   7628     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7629     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   7630     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   7631     cmp     r0, #0                      @ is resolved entry null?
   7632     beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
   7633 .LOP_SGET_WIDE_VOLATILE_finish:
   7634     mov     r9, rINST, lsr #8           @ r9<- AA
   7635     add     r0, r0, #offStaticField_value @ r0<- pointer to data
   7636     .if 1
   7637     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   7638     .else
   7639     ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
   7640     .endif
   7641     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   7642     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7643     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   7644     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7645     GOTO_OPCODE(ip)                     @ jump to next instruction
   7646 
   7647 
   7648 /* ------------------------------ */
   7649     .balign 64
   7650 .L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
   7651 /* File: armv4t/OP_SPUT_WIDE_VOLATILE.S */
   7652 /* File: armv4t/OP_SPUT_WIDE.S */
   7653     /*
   7654      * 64-bit SPUT handler.
   7655      */
   7656     /* sput-wide vAA, field@BBBB */
   7657     ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
   7658     FETCH(r1, 1)                        @ r1<- field ref BBBB
   7659     ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
   7660     mov     r9, rINST, lsr #8           @ r9<- AA
   7661     ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
   7662     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   7663     cmp     r2, #0                      @ is resolved entry null?
   7664     beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
   7665 .LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
   7666     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7667     ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
   7668     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   7669     add     r2, r2, #offStaticField_value @ r2<- pointer to data
   7670     .if 1
   7671     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   7672     .else
   7673     stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
   7674     .endif
   7675     GOTO_OPCODE(r10)                    @ jump to next instruction
   7676 
   7677 
   7678 /* ------------------------------ */
   7679     .balign 64
   7680 .L_OP_BREAKPOINT: /* 0xec */
   7681 /* File: armv5te/OP_BREAKPOINT.S */
   7682 /* File: armv5te/unused.S */
   7683     bl      common_abort
   7684 
   7685 
   7686 /* ------------------------------ */
   7687     .balign 64
   7688 .L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
   7689 /* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
   7690     /*
   7691      * Handle a throw-verification-error instruction.  This throws an
   7692      * exception for an error discovered during verification.  The
   7693      * exception is indicated by AA, with some detail provided by BBBB.
   7694      */
   7695     /* op AA, ref@BBBB */
   7696     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
   7697     FETCH(r2, 1)                        @ r2<- BBBB
   7698     EXPORT_PC()                         @ export the PC
   7699     mov     r1, rINST, lsr #8           @ r1<- AA
   7700     bl      dvmThrowVerificationError   @ always throws
   7701     b       common_exceptionThrown      @ handle exception
   7702 
   7703 /* ------------------------------ */
   7704     .balign 64
   7705 .L_OP_EXECUTE_INLINE: /* 0xee */
   7706 /* File: armv5te/OP_EXECUTE_INLINE.S */
   7707     /*
   7708      * Execute a "native inline" instruction.
   7709      *
   7710      * We need to call an InlineOp4Func:
   7711      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
   7712      *
   7713      * The first four args are in r0-r3, pointer to return value storage
   7714      * is on the stack.  The function's return value is a flag that tells
   7715      * us if an exception was thrown.
   7716      */
   7717     /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
   7718     FETCH(r10, 1)                       @ r10<- BBBB
   7719     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
   7720     EXPORT_PC()                         @ can throw
   7721     sub     sp, sp, #8                  @ make room for arg, +64 bit align
   7722     mov     r0, rINST, lsr #12          @ r0<- B
   7723     str     r1, [sp]                    @ push &glue->retval
   7724     bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
   7725     add     sp, sp, #8                  @ pop stack
   7726     cmp     r0, #0                      @ test boolean result of inline
   7727     beq     common_exceptionThrown      @ returned false, handle exception
   7728     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7729     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7730     GOTO_OPCODE(ip)                     @ jump to next instruction
   7731 
   7732 /* ------------------------------ */
   7733     .balign 64
   7734 .L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
   7735 /* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
   7736     /*
   7737      * Execute a "native inline" instruction, using "/range" semantics.
   7738      * Same idea as execute-inline, but we get the args differently.
   7739      *
   7740      * We need to call an InlineOp4Func:
   7741      *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
   7742      *
   7743      * The first four args are in r0-r3, pointer to return value storage
   7744      * is on the stack.  The function's return value is a flag that tells
   7745      * us if an exception was thrown.
   7746      */
   7747     /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
   7748     FETCH(r10, 1)                       @ r10<- BBBB
   7749     add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
   7750     EXPORT_PC()                         @ can throw
   7751     sub     sp, sp, #8                  @ make room for arg, +64 bit align
   7752     mov     r0, rINST, lsr #8           @ r0<- AA
   7753     str     r1, [sp]                    @ push &glue->retval
   7754     bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
   7755     add     sp, sp, #8                  @ pop stack
   7756     cmp     r0, #0                      @ test boolean result of inline
   7757     beq     common_exceptionThrown      @ returned false, handle exception
   7758     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   7759     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7760     GOTO_OPCODE(ip)                     @ jump to next instruction
   7761 
   7762 /* ------------------------------ */
   7763     .balign 64
   7764 .L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
   7765 /* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
   7766     /*
   7767      * invoke-direct-empty is a no-op in a "standard" interpreter.
   7768      */
   7769     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   7770     GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
   7771     GOTO_OPCODE(ip)                     @ execute it
   7772 
   7773 /* ------------------------------ */
   7774     .balign 64
   7775 .L_OP_UNUSED_F1: /* 0xf1 */
   7776 /* File: armv5te/OP_UNUSED_F1.S */
   7777 /* File: armv5te/unused.S */
   7778     bl      common_abort
   7779 
   7780 
   7781 /* ------------------------------ */
   7782     .balign 64
   7783 .L_OP_IGET_QUICK: /* 0xf2 */
   7784 /* File: armv5te/OP_IGET_QUICK.S */
   7785     /* For: iget-quick, iget-object-quick */
   7786     /* op vA, vB, offset@CCCC */
   7787     mov     r2, rINST, lsr #12          @ r2<- B
   7788     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7789     FETCH(r1, 1)                        @ r1<- field byte offset
   7790     cmp     r3, #0                      @ check object for null
   7791     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7792     beq     common_errNullObject        @ object was null
   7793     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
   7794     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7795     and     r2, r2, #15
   7796     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7797     SET_VREG(r0, r2)                    @ fp[A]<- r0
   7798     GOTO_OPCODE(ip)                     @ jump to next instruction
   7799 
   7800 /* ------------------------------ */
   7801     .balign 64
   7802 .L_OP_IGET_WIDE_QUICK: /* 0xf3 */
   7803 /* File: armv4t/OP_IGET_WIDE_QUICK.S */
   7804     /* iget-wide-quick vA, vB, offset@CCCC */
   7805     mov     r2, rINST, lsr #12          @ r2<- B
   7806     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7807     FETCH(r1, 1)                        @ r1<- field byte offset
   7808     cmp     r3, #0                      @ check object for null
   7809     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7810     beq     common_errNullObject        @ object was null
   7811     add     r9, r3, r1                  @ r9<- object + offset
   7812     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64 bits, aligned)
   7813     and     r2, r2, #15                 @ r2<- A
   7814     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7815     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   7816     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7817     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   7818     GOTO_OPCODE(ip)                     @ jump to next instruction
   7819 
   7820 /* ------------------------------ */
   7821     .balign 64
   7822 .L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
   7823 /* File: armv5te/OP_IGET_OBJECT_QUICK.S */
   7824 /* File: armv5te/OP_IGET_QUICK.S */
   7825     /* For: iget-quick, iget-object-quick */
   7826     /* op vA, vB, offset@CCCC */
   7827     mov     r2, rINST, lsr #12          @ r2<- B
   7828     GET_VREG(r3, r2)                    @ r3<- object we're operating on
   7829     FETCH(r1, 1)                        @ r1<- field byte offset
   7830     cmp     r3, #0                      @ check object for null
   7831     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7832     beq     common_errNullObject        @ object was null
   7833     ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
   7834     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7835     and     r2, r2, #15
   7836     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7837     SET_VREG(r0, r2)                    @ fp[A]<- r0
   7838     GOTO_OPCODE(ip)                     @ jump to next instruction
   7839 
   7840 
   7841 /* ------------------------------ */
   7842     .balign 64
   7843 .L_OP_IPUT_QUICK: /* 0xf5 */
   7844 /* File: armv5te/OP_IPUT_QUICK.S */
   7845     /* For: iput-quick */
   7846     /* op vA, vB, offset@CCCC */
   7847     mov     r2, rINST, lsr #12          @ r2<- B
   7848     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
   7849     FETCH(r1, 1)                        @ r1<- field byte offset
   7850     cmp     r3, #0                      @ check object for null
   7851     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7852     beq     common_errNullObject        @ object was null
   7853     and     r2, r2, #15
   7854     GET_VREG(r0, r2)                    @ r0<- fp[A]
   7855     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7856     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
   7857     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7858     GOTO_OPCODE(ip)                     @ jump to next instruction
   7859 
   7860 /* ------------------------------ */
   7861     .balign 64
   7862 .L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
   7863 /* File: armv4t/OP_IPUT_WIDE_QUICK.S */
   7864     /* iput-wide-quick vA, vB, offset@CCCC */
   7865     mov     r0, rINST, lsr #8           @ r0<- A(+)
   7866     mov     r1, rINST, lsr #12          @ r1<- B
   7867     and     r0, r0, #15
   7868     GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
   7869     add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
   7870     cmp     r2, #0                      @ check object for null
   7871     ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
   7872     beq     common_errNullObject        @ object was null
   7873     FETCH(r3, 1)                        @ r3<- field byte offset
   7874     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7875     add     r2, r2, r3                  @ r2<- object + byte offset
   7876     stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
   7877     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7878     GOTO_OPCODE(ip)                     @ jump to next instruction
   7879 
   7880 /* ------------------------------ */
   7881     .balign 64
   7882 .L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
   7883 /* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
   7884     /* For: iput-object-quick */
   7885     /* op vA, vB, offset@CCCC */
   7886     mov     r2, rINST, lsr #12          @ r2<- B
   7887     GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
   7888     FETCH(r1, 1)                        @ r1<- field byte offset
   7889     cmp     r3, #0                      @ check object for null
   7890     mov     r2, rINST, lsr #8           @ r2<- A(+)
   7891     beq     common_errNullObject        @ object was null
   7892     and     r2, r2, #15
   7893     GET_VREG(r0, r2)                    @ r0<- fp[A]
   7894     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   7895     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   7896     str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
   7897     cmp     r0, #0
   7898     strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
   7899     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   7900     GOTO_OPCODE(ip)                     @ jump to next instruction
   7901 
   7902 /* ------------------------------ */
   7903     .balign 64
   7904 .L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
   7905 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
   7906     /*
   7907      * Handle an optimized virtual method call.
   7908      *
   7909      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
   7910      */
   7911     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7912     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7913     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
   7914     FETCH(r1, 1)                        @ r1<- BBBB
   7915     .if     (!0)
   7916     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
   7917     .endif
   7918     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
   7919     cmp     r2, #0                      @ is "this" null?
   7920     beq     common_errNullObject        @ null "this", throw exception
   7921     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
   7922     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
   7923     EXPORT_PC()                         @ invoke must export
   7924     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
   7925     bl      common_invokeMethodNoRange @ continue on
   7926 
   7927 /* ------------------------------ */
   7928     .balign 64
   7929 .L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
   7930 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
   7931 /* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
   7932     /*
   7933      * Handle an optimized virtual method call.
   7934      *
   7935      * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
   7936      */
   7937     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7938     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7939     FETCH(r3, 2)                        @ r3<- FEDC or CCCC
   7940     FETCH(r1, 1)                        @ r1<- BBBB
   7941     .if     (!1)
   7942     and     r3, r3, #15                 @ r3<- C (or stays CCCC)
   7943     .endif
   7944     GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
   7945     cmp     r2, #0                      @ is "this" null?
   7946     beq     common_errNullObject        @ null "this", throw exception
   7947     ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
   7948     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
   7949     EXPORT_PC()                         @ invoke must export
   7950     ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
   7951     bl      common_invokeMethodRange @ continue on
   7952 
   7953 
   7954 /* ------------------------------ */
   7955     .balign 64
   7956 .L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
   7957 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
   7958     /*
   7959      * Handle an optimized "super" method call.
   7960      *
   7961      * for: [opt] invoke-super-quick, invoke-super-quick/range
   7962      */
   7963     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7964     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7965     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   7966     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7967     .if     (!0)
   7968     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   7969     .endif
   7970     FETCH(r1, 1)                        @ r1<- BBBB
   7971     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
   7972     EXPORT_PC()                         @ must export for invoke
   7973     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
   7974     GET_VREG(r3, r10)                   @ r3<- "this"
   7975     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
   7976     cmp     r3, #0                      @ null "this" ref?
   7977     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
   7978     beq     common_errNullObject        @ "this" is null, throw exception
   7979     bl      common_invokeMethodNoRange @ continue on
   7980 
   7981 /* ------------------------------ */
   7982     .balign 64
   7983 .L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
   7984 /* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
   7985 /* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
   7986     /*
   7987      * Handle an optimized "super" method call.
   7988      *
   7989      * for: [opt] invoke-super-quick, invoke-super-quick/range
   7990      */
   7991     /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
   7992     /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
   7993     FETCH(r10, 2)                       @ r10<- GFED or CCCC
   7994     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   7995     .if     (!1)
   7996     and     r10, r10, #15               @ r10<- D (or stays CCCC)
   7997     .endif
   7998     FETCH(r1, 1)                        @ r1<- BBBB
   7999     ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
   8000     EXPORT_PC()                         @ must export for invoke
   8001     ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
   8002     GET_VREG(r3, r10)                   @ r3<- "this"
   8003     ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
   8004     cmp     r3, #0                      @ null "this" ref?
   8005     ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
   8006     beq     common_errNullObject        @ "this" is null, throw exception
   8007     bl      common_invokeMethodRange @ continue on
   8008 
   8009 
   8010 /* ------------------------------ */
   8011     .balign 64
   8012 .L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
   8013 /* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
   8014 /* File: armv5te/OP_IPUT_OBJECT.S */
   8015     /*
   8016      * 32-bit instance field put.
   8017      *
   8018      * for: iput-object, iput-object-volatile
   8019      */
   8020     /* op vA, vB, field@CCCC */
   8021     mov     r0, rINST, lsr #12          @ r0<- B
   8022     ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
   8023     FETCH(r1, 1)                        @ r1<- field ref CCCC
   8024     ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
   8025     GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
   8026     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
   8027     cmp     r0, #0                      @ is resolved entry null?
   8028     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
   8029 8:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   8030     EXPORT_PC()                         @ resolve() could throw
   8031     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   8032     bl      dvmResolveInstField         @ r0<- resolved InstField ptr
   8033     cmp     r0, #0                      @ success?
   8034     bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
   8035     b       common_exceptionThrown
   8036 
   8037 
   8038 /* ------------------------------ */
   8039     .balign 64
   8040 .L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
   8041 /* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
   8042 /* File: armv5te/OP_SGET.S */
   8043     /*
   8044      * General 32-bit SGET handler.
   8045      *
   8046      * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
   8047      */
   8048     /* op vAA, field@BBBB */
   8049     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   8050     FETCH(r1, 1)                        @ r1<- field ref BBBB
   8051     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   8052     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   8053     cmp     r0, #0                      @ is resolved entry null?
   8054     beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
   8055 .LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
   8056     ldr     r1, [r0, #offStaticField_value] @ r1<- field value
   8057     SMP_DMB                            @ acquiring load
   8058     mov     r2, rINST, lsr #8           @ r2<- AA
   8059     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8060     SET_VREG(r1, r2)                    @ fp[AA]<- r1
   8061     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8062     GOTO_OPCODE(ip)                     @ jump to next instruction
   8063 
   8064 
   8065 /* ------------------------------ */
   8066     .balign 64
   8067 .L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
   8068 /* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
   8069 /* File: armv5te/OP_SPUT_OBJECT.S */
   8070     /*
   8071      * 32-bit SPUT handler for objects
   8072      *
   8073      * for: sput-object, sput-object-volatile
   8074      */
   8075     /* op vAA, field@BBBB */
   8076     ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
   8077     FETCH(r1, 1)                        @ r1<- field ref BBBB
   8078     ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
   8079     ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
   8080     cmp     r0, #0                      @ is resolved entry null?
   8081     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
   8082     ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
   8083     EXPORT_PC()                         @ resolve() could throw, so export now
   8084     ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
   8085     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   8086     cmp     r0, #0                      @ success?
   8087     bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
   8088     b       common_exceptionThrown      @ no, handle exception
   8089 
   8090 
   8091 
   8092 /* ------------------------------ */
   8093     .balign 64
   8094 .L_OP_UNUSED_FF: /* 0xff */
   8095 /* File: armv5te/OP_UNUSED_FF.S */
   8096 /* File: armv5te/unused.S */
   8097     bl      common_abort
   8098 
   8099 
   8100 
   8101     .balign 64
   8102     .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
   8103     .global dvmAsmInstructionEnd
   8104 dvmAsmInstructionEnd:
   8105 
   8106 /*
   8107  * ===========================================================================
   8108  *  Sister implementations
   8109  * ===========================================================================
   8110  */
   8111     .global dvmAsmSisterStart
   8112     .type   dvmAsmSisterStart, %function
   8113     .text
   8114     .balign 4
   8115 dvmAsmSisterStart:
   8116 
   8117 /* continuation for OP_CONST_STRING */
   8118 
   8119     /*
   8120      * Continuation if the String has not yet been resolved.
   8121      *  r1: BBBB (String ref)
   8122      *  r9: target register
   8123      */
   8124 .LOP_CONST_STRING_resolve:
   8125     EXPORT_PC()
   8126     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   8127     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   8128     bl      dvmResolveString            @ r0<- String reference
   8129     cmp     r0, #0                      @ failed?
   8130     beq     common_exceptionThrown      @ yup, handle the exception
   8131     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8132     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8133     SET_VREG(r0, r9)                    @ vAA<- r0
   8134     GOTO_OPCODE(ip)                     @ jump to next instruction
   8135 
   8136 /* continuation for OP_CONST_STRING_JUMBO */
   8137 
   8138     /*
   8139      * Continuation if the String has not yet been resolved.
   8140      *  r1: BBBBBBBB (String ref)
   8141      *  r9: target register
   8142      */
   8143 .LOP_CONST_STRING_JUMBO_resolve:
   8144     EXPORT_PC()
   8145     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   8146     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   8147     bl      dvmResolveString            @ r0<- String reference
   8148     cmp     r0, #0                      @ failed?
   8149     beq     common_exceptionThrown      @ yup, handle the exception
   8150     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   8151     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8152     SET_VREG(r0, r9)                    @ vAA<- r0
   8153     GOTO_OPCODE(ip)                     @ jump to next instruction
   8154 
   8155 /* continuation for OP_CONST_CLASS */
   8156 
   8157     /*
   8158      * Continuation if the Class has not yet been resolved.
   8159      *  r1: BBBB (Class ref)
   8160      *  r9: target register
   8161      */
   8162 .LOP_CONST_CLASS_resolve:
   8163     EXPORT_PC()
   8164     ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
   8165     mov     r2, #1                      @ r2<- true
   8166     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   8167     bl      dvmResolveClass             @ r0<- Class reference
   8168     cmp     r0, #0                      @ failed?
   8169     beq     common_exceptionThrown      @ yup, handle the exception
   8170     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8171     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8172     SET_VREG(r0, r9)                    @ vAA<- r0
   8173     GOTO_OPCODE(ip)                     @ jump to next instruction
   8174 
   8175 /* continuation for OP_CHECK_CAST */
   8176 
   8177     /*
   8178      * Trivial test failed, need to perform full check.  This is common.
   8179      *  r0 holds obj->clazz
   8180      *  r1 holds class resolved from BBBB
   8181      *  r9 holds object
   8182      */
   8183 .LOP_CHECK_CAST_fullcheck:
   8184     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
   8185     cmp     r0, #0                      @ failed?
   8186     bne     .LOP_CHECK_CAST_okay            @ no, success
   8187 
   8188     @ A cast has failed.  We need to throw a ClassCastException with the
   8189     @ class of the object that failed to be cast.
   8190     EXPORT_PC()                         @ about to throw
   8191     ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
   8192     ldr     r0, .LstrClassCastExceptionPtr
   8193     ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
   8194     bl      dvmThrowExceptionWithClassMessage
   8195     b       common_exceptionThrown
   8196 
   8197     /*
   8198      * Resolution required.  This is the least-likely path.
   8199      *
   8200      *  r2 holds BBBB
   8201      *  r9 holds object
   8202      */
   8203 .LOP_CHECK_CAST_resolve:
   8204     EXPORT_PC()                         @ resolve() could throw
   8205     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8206     mov     r1, r2                      @ r1<- BBBB
   8207     mov     r2, #0                      @ r2<- false
   8208     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8209     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   8210     cmp     r0, #0                      @ got null?
   8211     beq     common_exceptionThrown      @ yes, handle exception
   8212     mov     r1, r0                      @ r1<- class resolved from BBB
   8213     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
   8214     b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
   8215 
   8216 .LstrClassCastExceptionPtr:
   8217     .word   .LstrClassCastException
   8218 
   8219 /* continuation for OP_INSTANCE_OF */
   8220 
   8221     /*
   8222      * Trivial test failed, need to perform full check.  This is common.
   8223      *  r0 holds obj->clazz
   8224      *  r1 holds class resolved from BBBB
   8225      *  r9 holds A
   8226      */
   8227 .LOP_INSTANCE_OF_fullcheck:
   8228     bl      dvmInstanceofNonTrivial     @ r0<- boolean result
   8229     @ fall through to OP_INSTANCE_OF_store
   8230 
   8231     /*
   8232      * r0 holds boolean result
   8233      * r9 holds A
   8234      */
   8235 .LOP_INSTANCE_OF_store:
   8236     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8237     SET_VREG(r0, r9)                    @ vA<- r0
   8238     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8239     GOTO_OPCODE(ip)                     @ jump to next instruction
   8240 
   8241     /*
   8242      * Trivial test succeeded, save and bail.
   8243      *  r9 holds A
   8244      */
   8245 .LOP_INSTANCE_OF_trivial:
   8246     mov     r0, #1                      @ indicate success
   8247     @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
   8248     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8249     SET_VREG(r0, r9)                    @ vA<- r0
   8250     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8251     GOTO_OPCODE(ip)                     @ jump to next instruction
   8252 
   8253     /*
   8254      * Resolution required.  This is the least-likely path.
   8255      *
   8256      *  r3 holds BBBB
   8257      *  r9 holds A
   8258      */
   8259 .LOP_INSTANCE_OF_resolve:
   8260     EXPORT_PC()                         @ resolve() could throw
   8261     ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
   8262     mov     r1, r3                      @ r1<- BBBB
   8263     mov     r2, #1                      @ r2<- true
   8264     ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
   8265     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   8266     cmp     r0, #0                      @ got null?
   8267     beq     common_exceptionThrown      @ yes, handle exception
   8268     mov     r1, r0                      @ r1<- class resolved from BBB
   8269     mov     r3, rINST, lsr #12          @ r3<- B
   8270     GET_VREG(r0, r3)                    @ r0<- vB (object)
   8271     ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
   8272     b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
   8273 
   8274 /* continuation for OP_NEW_INSTANCE */
   8275 
   8276     .balign 32                          @ minimize cache lines
   8277 .LOP_NEW_INSTANCE_finish: @ r0=new object
   8278     mov     r3, rINST, lsr #8           @ r3<- AA
   8279     cmp     r0, #0                      @ failed?
   8280     beq     common_exceptionThrown      @ yes, handle the exception
   8281     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8282     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8283     SET_VREG(r0, r3)                    @ vAA<- r0
   8284     GOTO_OPCODE(ip)                     @ jump to next instruction
   8285 
   8286     /*
   8287      * Class initialization required.
   8288      *
   8289      *  r0 holds class object
   8290      */
   8291 .LOP_NEW_INSTANCE_needinit:
   8292     mov     r9, r0                      @ save r0
   8293     bl      dvmInitClass                @ initialize class
   8294     cmp     r0, #0                      @ check boolean result
   8295     mov     r0, r9                      @ restore r0
   8296     bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
   8297     b       common_exceptionThrown      @ failed, deal with init exception
   8298 
   8299     /*
   8300      * Resolution required.  This is the least-likely path.
   8301      *
   8302      *  r1 holds BBBB
   8303      */
   8304 .LOP_NEW_INSTANCE_resolve:
   8305     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8306     mov     r2, #0                      @ r2<- false
   8307     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8308     bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
   8309     cmp     r0, #0                      @ got null?
   8310     bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
   8311     b       common_exceptionThrown      @ yes, handle exception
   8312 
   8313 .LstrInstantiationErrorPtr:
   8314     .word   .LstrInstantiationError
   8315 
   8316 /* continuation for OP_NEW_ARRAY */
   8317 
   8318 
   8319     /*
   8320      * Resolve class.  (This is an uncommon case.)
   8321      *
   8322      *  r1 holds array length
   8323      *  r2 holds class ref CCCC
   8324      */
   8325 .LOP_NEW_ARRAY_resolve:
   8326     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   8327     mov     r9, r1                      @ r9<- length (save)
   8328     mov     r1, r2                      @ r1<- CCCC
   8329     mov     r2, #0                      @ r2<- false
   8330     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   8331     bl      dvmResolveClass             @ r0<- call(clazz, ref)
   8332     cmp     r0, #0                      @ got null?
   8333     mov     r1, r9                      @ r1<- length (restore)
   8334     beq     common_exceptionThrown      @ yes, handle exception
   8335     @ fall through to OP_NEW_ARRAY_finish
   8336 
   8337     /*
   8338      * Finish allocation.
   8339      *
   8340      *  r0 holds class
   8341      *  r1 holds array length
   8342      */
   8343 .LOP_NEW_ARRAY_finish:
   8344     mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
   8345     bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
   8346     cmp     r0, #0                      @ failed?
   8347     mov     r2, rINST, lsr #8           @ r2<- A+
   8348     beq     common_exceptionThrown      @ yes, handle the exception
   8349     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8350     and     r2, r2, #15                 @ r2<- A
   8351     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8352     SET_VREG(r0, r2)                    @ vA<- r0
   8353     GOTO_OPCODE(ip)                     @ jump to next instruction
   8354 
   8355 /* continuation for OP_FILLED_NEW_ARRAY */
   8356 
   8357     /*
   8358      * On entry:
   8359      *  r0 holds array class
   8360      *  r10 holds AA or BA
   8361      */
   8362 .LOP_FILLED_NEW_ARRAY_continue:
   8363     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
   8364     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
   8365     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
   8366     .if     0
   8367     mov     r1, r10                     @ r1<- AA (length)
   8368     .else
   8369     mov     r1, r10, lsr #4             @ r1<- B (length)
   8370     .endif
   8371     cmp     rINST, #'I'                 @ array of ints?
   8372     cmpne   rINST, #'L'                 @ array of objects?
   8373     cmpne   rINST, #'['                 @ array of arrays?
   8374     mov     r9, r1                      @ save length in r9
   8375     bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
   8376     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
   8377     cmp     r0, #0                      @ null return?
   8378     beq     common_exceptionThrown      @ alloc failed, handle exception
   8379 
   8380     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
   8381     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
   8382     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
   8383     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
   8384     subs    r9, r9, #1                  @ length--, check for neg
   8385     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   8386     bmi     2f                          @ was zero, bail
   8387 
   8388     @ copy values from registers into the array
   8389     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
   8390     .if     0
   8391     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
   8392 1:  ldr     r3, [r2], #4                @ r3<- *r2++
   8393     subs    r9, r9, #1                  @ count--
   8394     str     r3, [r0], #4                @ *contents++ = vX
   8395     bpl     1b
   8396     @ continue at 2
   8397     .else
   8398     cmp     r9, #4                      @ length was initially 5?
   8399     and     r2, r10, #15                @ r2<- A
   8400     bne     1f                          @ <= 4 args, branch
   8401     GET_VREG(r3, r2)                    @ r3<- vA
   8402     sub     r9, r9, #1                  @ count--
   8403     str     r3, [r0, #16]               @ contents[4] = vA
   8404 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
   8405     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
   8406     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
   8407     subs    r9, r9, #1                  @ count--
   8408     str     r3, [r0], #4                @ *contents++ = vX
   8409     bpl     1b
   8410     @ continue at 2
   8411     .endif
   8412 
   8413 2:
   8414     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
   8415     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
   8416     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8417     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
   8418     cmp     r1, #'I'                         @ Is int array?
   8419     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
   8420     GOTO_OPCODE(ip)                          @ execute it
   8421 
   8422     /*
   8423      * Throw an exception indicating that we have not implemented this
   8424      * mode of filled-new-array.
   8425      */
   8426 .LOP_FILLED_NEW_ARRAY_notimpl:
   8427     ldr     r0, .L_strInternalError
   8428     ldr     r1, .L_strFilledNewArrayNotImpl
   8429     bl      dvmThrowException
   8430     b       common_exceptionThrown
   8431 
   8432     .if     (!0)                 @ define in one or the other, not both
   8433 .L_strFilledNewArrayNotImpl:
   8434     .word   .LstrFilledNewArrayNotImpl
   8435 .L_strInternalError:
   8436     .word   .LstrInternalError
   8437     .endif
   8438 
   8439 /* continuation for OP_FILLED_NEW_ARRAY_RANGE */
   8440 
   8441     /*
   8442      * On entry:
   8443      *  r0 holds array class
   8444      *  r10 holds AA or BA
   8445      */
   8446 .LOP_FILLED_NEW_ARRAY_RANGE_continue:
   8447     ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
   8448     mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
   8449     ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
   8450     .if     1
   8451     mov     r1, r10                     @ r1<- AA (length)
   8452     .else
   8453     mov     r1, r10, lsr #4             @ r1<- B (length)
   8454     .endif
   8455     cmp     rINST, #'I'                 @ array of ints?
   8456     cmpne   rINST, #'L'                 @ array of objects?
   8457     cmpne   rINST, #'['                 @ array of arrays?
   8458     mov     r9, r1                      @ save length in r9
   8459     bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
   8460     bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
   8461     cmp     r0, #0                      @ null return?
   8462     beq     common_exceptionThrown      @ alloc failed, handle exception
   8463 
   8464     FETCH(r1, 2)                        @ r1<- FEDC or CCCC
   8465     str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
   8466     str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
   8467     add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
   8468     subs    r9, r9, #1                  @ length--, check for neg
   8469     FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
   8470     bmi     2f                          @ was zero, bail
   8471 
   8472     @ copy values from registers into the array
   8473     @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
   8474     .if     1
   8475     add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
   8476 1:  ldr     r3, [r2], #4                @ r3<- *r2++
   8477     subs    r9, r9, #1                  @ count--
   8478     str     r3, [r0], #4                @ *contents++ = vX
   8479     bpl     1b
   8480     @ continue at 2
   8481     .else
   8482     cmp     r9, #4                      @ length was initially 5?
   8483     and     r2, r10, #15                @ r2<- A
   8484     bne     1f                          @ <= 4 args, branch
   8485     GET_VREG(r3, r2)                    @ r3<- vA
   8486     sub     r9, r9, #1                  @ count--
   8487     str     r3, [r0, #16]               @ contents[4] = vA
   8488 1:  and     r2, r1, #15                 @ r2<- F/E/D/C
   8489     GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
   8490     mov     r1, r1, lsr #4              @ r1<- next reg in low 4
   8491     subs    r9, r9, #1                  @ count--
   8492     str     r3, [r0], #4                @ *contents++ = vX
   8493     bpl     1b
   8494     @ continue at 2
   8495     .endif
   8496 
   8497 2:
   8498     ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
   8499     ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
   8500     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8501     GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
   8502     cmp     r1, #'I'                         @ Is int array?
   8503     strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
   8504     GOTO_OPCODE(ip)                          @ execute it
   8505 
   8506     /*
   8507      * Throw an exception indicating that we have not implemented this
   8508      * mode of filled-new-array.
   8509      */
   8510 .LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
   8511     ldr     r0, .L_strInternalError
   8512     ldr     r1, .L_strFilledNewArrayNotImpl
   8513     bl      dvmThrowException
   8514     b       common_exceptionThrown
   8515 
   8516     .if     (!1)                 @ define in one or the other, not both
   8517 .L_strFilledNewArrayNotImpl:
   8518     .word   .LstrFilledNewArrayNotImpl
   8519 .L_strInternalError:
   8520     .word   .LstrInternalError
   8521     .endif
   8522 
   8523 /* continuation for OP_CMPL_FLOAT */
   8524 
   8525     @ Test for NaN with a second comparison.  EABI forbids testing bit
   8526     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
   8527     @ make the library call.
   8528 .LOP_CMPL_FLOAT_gt_or_nan:
   8529     mov     r1, r9                      @ reverse order
   8530     mov     r0, r10
   8531     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
   8532     @bleq    common_abort
   8533     movcc   r1, #1                      @ (greater than) r1<- 1
   8534     bcc     .LOP_CMPL_FLOAT_finish
   8535     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
   8536     b       .LOP_CMPL_FLOAT_finish
   8537 
   8538 
   8539 #if 0       /* "clasic" form */
   8540     FETCH(r0, 1)                        @ r0<- CCBB
   8541     and     r2, r0, #255                @ r2<- BB
   8542     mov     r3, r0, lsr #8              @ r3<- CC
   8543     GET_VREG(r9, r2)                    @ r9<- vBB
   8544     GET_VREG(r10, r3)                   @ r10<- vCC
   8545     mov     r0, r9                      @ r0<- vBB
   8546     mov     r1, r10                     @ r1<- vCC
   8547     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
   8548     cmp     r0, #0                      @ equal?
   8549     movne   r1, #0                      @ yes, result is 0
   8550     bne     OP_CMPL_FLOAT_finish
   8551     mov     r0, r9                      @ r0<- vBB
   8552     mov     r1, r10                     @ r1<- vCC
   8553     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
   8554     cmp     r0, #0                      @ less than?
   8555     b       OP_CMPL_FLOAT_continue
   8556 @%break
   8557 
   8558 OP_CMPL_FLOAT_continue:
   8559     mvnne   r1, #0                      @ yes, result is -1
   8560     bne     OP_CMPL_FLOAT_finish
   8561     mov     r0, r9                      @ r0<- vBB
   8562     mov     r1, r10                     @ r1<- vCC
   8563     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
   8564     cmp     r0, #0                      @ greater than?
   8565     beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
   8566     mov     r1, #1                      @ yes, result is 1
   8567     @ fall through to _finish
   8568 
   8569 OP_CMPL_FLOAT_finish:
   8570     mov     r3, rINST, lsr #8           @ r3<- AA
   8571     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8572     SET_VREG(r1, r3)                    @ vAA<- r1
   8573     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8574     GOTO_OPCODE(ip)                     @ jump to next instruction
   8575 
   8576     /*
   8577      * This is expected to be uncommon, so we double-branch (once to here,
   8578      * again back to _finish).
   8579      */
   8580 OP_CMPL_FLOAT_nan:
   8581     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
   8582     b       OP_CMPL_FLOAT_finish
   8583 
   8584 #endif
   8585 
   8586 /* continuation for OP_CMPG_FLOAT */
   8587 
   8588     @ Test for NaN with a second comparison.  EABI forbids testing bit
   8589     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
   8590     @ make the library call.
   8591 .LOP_CMPG_FLOAT_gt_or_nan:
   8592     mov     r1, r9                      @ reverse order
   8593     mov     r0, r10
   8594     bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
   8595     @bleq    common_abort
   8596     movcc   r1, #1                      @ (greater than) r1<- 1
   8597     bcc     .LOP_CMPG_FLOAT_finish
   8598     mov     r1, #1                            @ r1<- 1 or -1 for NaN
   8599     b       .LOP_CMPG_FLOAT_finish
   8600 
   8601 
   8602 #if 0       /* "clasic" form */
   8603     FETCH(r0, 1)                        @ r0<- CCBB
   8604     and     r2, r0, #255                @ r2<- BB
   8605     mov     r3, r0, lsr #8              @ r3<- CC
   8606     GET_VREG(r9, r2)                    @ r9<- vBB
   8607     GET_VREG(r10, r3)                   @ r10<- vCC
   8608     mov     r0, r9                      @ r0<- vBB
   8609     mov     r1, r10                     @ r1<- vCC
   8610     bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
   8611     cmp     r0, #0                      @ equal?
   8612     movne   r1, #0                      @ yes, result is 0
   8613     bne     OP_CMPG_FLOAT_finish
   8614     mov     r0, r9                      @ r0<- vBB
   8615     mov     r1, r10                     @ r1<- vCC
   8616     bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
   8617     cmp     r0, #0                      @ less than?
   8618     b       OP_CMPG_FLOAT_continue
   8619 @%break
   8620 
   8621 OP_CMPG_FLOAT_continue:
   8622     mvnne   r1, #0                      @ yes, result is -1
   8623     bne     OP_CMPG_FLOAT_finish
   8624     mov     r0, r9                      @ r0<- vBB
   8625     mov     r1, r10                     @ r1<- vCC
   8626     bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
   8627     cmp     r0, #0                      @ greater than?
   8628     beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
   8629     mov     r1, #1                      @ yes, result is 1
   8630     @ fall through to _finish
   8631 
   8632 OP_CMPG_FLOAT_finish:
   8633     mov     r3, rINST, lsr #8           @ r3<- AA
   8634     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8635     SET_VREG(r1, r3)                    @ vAA<- r1
   8636     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8637     GOTO_OPCODE(ip)                     @ jump to next instruction
   8638 
   8639     /*
   8640      * This is expected to be uncommon, so we double-branch (once to here,
   8641      * again back to _finish).
   8642      */
   8643 OP_CMPG_FLOAT_nan:
   8644     mov     r1, #1                            @ r1<- 1 or -1 for NaN
   8645     b       OP_CMPG_FLOAT_finish
   8646 
   8647 #endif
   8648 
   8649 /* continuation for OP_CMPL_DOUBLE */
   8650 
   8651     @ Test for NaN with a second comparison.  EABI forbids testing bit
   8652     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
   8653     @ make the library call.
   8654 .LOP_CMPL_DOUBLE_gt_or_nan:
   8655     ldmia   r10, {r0-r1}                @ reverse order
   8656     ldmia   r9, {r2-r3}
   8657     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
   8658     @bleq    common_abort
   8659     movcc   r1, #1                      @ (greater than) r1<- 1
   8660     bcc     .LOP_CMPL_DOUBLE_finish
   8661     mvn     r1, #0                            @ r1<- 1 or -1 for NaN
   8662     b       .LOP_CMPL_DOUBLE_finish
   8663 
   8664 /* continuation for OP_CMPG_DOUBLE */
   8665 
   8666     @ Test for NaN with a second comparison.  EABI forbids testing bit
   8667     @ patterns, and we can't represent 0x7fc00000 in immediate form, so
   8668     @ make the library call.
   8669 .LOP_CMPG_DOUBLE_gt_or_nan:
   8670     ldmia   r10, {r0-r1}                @ reverse order
   8671     ldmia   r9, {r2-r3}
   8672     bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
   8673     @bleq    common_abort
   8674     movcc   r1, #1                      @ (greater than) r1<- 1
   8675     bcc     .LOP_CMPG_DOUBLE_finish
   8676     mov     r1, #1                            @ r1<- 1 or -1 for NaN
   8677     b       .LOP_CMPG_DOUBLE_finish
   8678 
   8679 /* continuation for OP_CMP_LONG */
   8680 
   8681 .LOP_CMP_LONG_less:
   8682     mvn     r1, #0                      @ r1<- -1
   8683     @ Want to cond code the next mov so we can avoid branch, but don't see it;
   8684     @ instead, we just replicate the tail end.
   8685     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8686     SET_VREG(r1, r9)                    @ vAA<- r1
   8687     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8688     GOTO_OPCODE(ip)                     @ jump to next instruction
   8689 
   8690 .LOP_CMP_LONG_greater:
   8691     mov     r1, #1                      @ r1<- 1
   8692     @ fall through to _finish
   8693 
   8694 .LOP_CMP_LONG_finish:
   8695     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8696     SET_VREG(r1, r9)                    @ vAA<- r1
   8697     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8698     GOTO_OPCODE(ip)                     @ jump to next instruction
   8699 
   8700 /* continuation for OP_AGET_WIDE */
   8701 
   8702 .LOP_AGET_WIDE_finish:
   8703     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8704     add     r0, r0, #offArrayObject_contents
   8705     ldmia   r0, {r2-r3}                 @ r2/r3 <- vBB[vCC]
   8706     add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
   8707     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8708     stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
   8709     GOTO_OPCODE(ip)                     @ jump to next instruction
   8710 
   8711 /* continuation for OP_APUT_WIDE */
   8712 
   8713 .LOP_APUT_WIDE_finish:
   8714     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8715     ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
   8716     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8717     add     r0, #offArrayObject_contents
   8718     stmia   r0, {r2-r3}                 @ vBB[vCC] <- r2/r3
   8719     GOTO_OPCODE(ip)                     @ jump to next instruction
   8720 
   8721 /* continuation for OP_APUT_OBJECT */
   8722     /*
   8723      * On entry:
   8724      *  rINST = vBB (arrayObj)
   8725      *  r9 = vAA (obj)
   8726      *  r10 = offset into array (vBB + vCC * width)
   8727      */
   8728 .LOP_APUT_OBJECT_finish:
   8729     cmp     r9, #0                      @ storing null reference?
   8730     beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
   8731     ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
   8732     ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
   8733     bl      dvmCanPutArrayElement       @ test object type vs. array type
   8734     cmp     r0, #0                      @ okay?
   8735     beq     common_errArrayStore        @ no
   8736     mov     r1, rINST                   @ r1<- arrayObj
   8737     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8738     ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
   8739     add     r10, #offArrayObject_contents   @ r0<- pointer to slot
   8740     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8741     str     r9, [r10]                   @ vBB[vCC]<- vAA
   8742     strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
   8743     GOTO_OPCODE(ip)                     @ jump to next instruction
   8744 .LOP_APUT_OBJECT_skip_check:
   8745     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8746     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8747     str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
   8748     GOTO_OPCODE(ip)                     @ jump to next instruction
   8749 
   8750 /* continuation for OP_IGET */
   8751 
   8752     /*
   8753      * Currently:
   8754      *  r0 holds resolved field
   8755      *  r9 holds object
   8756      */
   8757 .LOP_IGET_finish:
   8758     @bl      common_squeak0
   8759     cmp     r9, #0                      @ check object for null
   8760     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8761     beq     common_errNullObject        @ object was null
   8762     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8763     @ no-op                             @ acquiring load
   8764     mov     r2, rINST, lsr #8           @ r2<- A+
   8765     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8766     and     r2, r2, #15                 @ r2<- A
   8767     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8768     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8769     GOTO_OPCODE(ip)                     @ jump to next instruction
   8770 
   8771 /* continuation for OP_IGET_WIDE */
   8772 
   8773     /*
   8774      * Currently:
   8775      *  r0 holds resolved field
   8776      *  r9 holds object
   8777      */
   8778 .LOP_IGET_WIDE_finish:
   8779     cmp     r9, #0                      @ check object for null
   8780     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8781     beq     common_errNullObject        @ object was null
   8782     .if 0
   8783     add     r0, r9, r3                  @ r0<- address of field
   8784     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   8785     .else
   8786     add     r9, r9, r3                  @ r9<- obj + field offset
   8787     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
   8788     .endif
   8789     mov     r2, rINST, lsr #8           @ r2<- A+
   8790     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8791     and     r2, r2, #15                 @ r2<- A
   8792     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   8793     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8794     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   8795     GOTO_OPCODE(ip)                     @ jump to next instruction
   8796 
   8797 /* continuation for OP_IGET_OBJECT */
   8798 
   8799     /*
   8800      * Currently:
   8801      *  r0 holds resolved field
   8802      *  r9 holds object
   8803      */
   8804 .LOP_IGET_OBJECT_finish:
   8805     @bl      common_squeak0
   8806     cmp     r9, #0                      @ check object for null
   8807     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8808     beq     common_errNullObject        @ object was null
   8809     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8810     @ no-op                             @ acquiring load
   8811     mov     r2, rINST, lsr #8           @ r2<- A+
   8812     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8813     and     r2, r2, #15                 @ r2<- A
   8814     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8815     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8816     GOTO_OPCODE(ip)                     @ jump to next instruction
   8817 
   8818 /* continuation for OP_IGET_BOOLEAN */
   8819 
   8820     /*
   8821      * Currently:
   8822      *  r0 holds resolved field
   8823      *  r9 holds object
   8824      */
   8825 .LOP_IGET_BOOLEAN_finish:
   8826     @bl      common_squeak1
   8827     cmp     r9, #0                      @ check object for null
   8828     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8829     beq     common_errNullObject        @ object was null
   8830     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8831     @ no-op                             @ acquiring load
   8832     mov     r2, rINST, lsr #8           @ r2<- A+
   8833     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8834     and     r2, r2, #15                 @ r2<- A
   8835     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8836     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8837     GOTO_OPCODE(ip)                     @ jump to next instruction
   8838 
   8839 /* continuation for OP_IGET_BYTE */
   8840 
   8841     /*
   8842      * Currently:
   8843      *  r0 holds resolved field
   8844      *  r9 holds object
   8845      */
   8846 .LOP_IGET_BYTE_finish:
   8847     @bl      common_squeak2
   8848     cmp     r9, #0                      @ check object for null
   8849     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8850     beq     common_errNullObject        @ object was null
   8851     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8852     @ no-op                             @ acquiring load
   8853     mov     r2, rINST, lsr #8           @ r2<- A+
   8854     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8855     and     r2, r2, #15                 @ r2<- A
   8856     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8857     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8858     GOTO_OPCODE(ip)                     @ jump to next instruction
   8859 
   8860 /* continuation for OP_IGET_CHAR */
   8861 
   8862     /*
   8863      * Currently:
   8864      *  r0 holds resolved field
   8865      *  r9 holds object
   8866      */
   8867 .LOP_IGET_CHAR_finish:
   8868     @bl      common_squeak3
   8869     cmp     r9, #0                      @ check object for null
   8870     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8871     beq     common_errNullObject        @ object was null
   8872     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8873     @ no-op                             @ acquiring load
   8874     mov     r2, rINST, lsr #8           @ r2<- A+
   8875     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8876     and     r2, r2, #15                 @ r2<- A
   8877     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8878     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8879     GOTO_OPCODE(ip)                     @ jump to next instruction
   8880 
   8881 /* continuation for OP_IGET_SHORT */
   8882 
   8883     /*
   8884      * Currently:
   8885      *  r0 holds resolved field
   8886      *  r9 holds object
   8887      */
   8888 .LOP_IGET_SHORT_finish:
   8889     @bl      common_squeak4
   8890     cmp     r9, #0                      @ check object for null
   8891     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8892     beq     common_errNullObject        @ object was null
   8893     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   8894     @ no-op                             @ acquiring load
   8895     mov     r2, rINST, lsr #8           @ r2<- A+
   8896     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8897     and     r2, r2, #15                 @ r2<- A
   8898     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8899     SET_VREG(r0, r2)                    @ fp[A]<- r0
   8900     GOTO_OPCODE(ip)                     @ jump to next instruction
   8901 
   8902 /* continuation for OP_IPUT */
   8903 
   8904     /*
   8905      * Currently:
   8906      *  r0 holds resolved field
   8907      *  r9 holds object
   8908      */
   8909 .LOP_IPUT_finish:
   8910     @bl      common_squeak0
   8911     mov     r1, rINST, lsr #8           @ r1<- A+
   8912     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8913     and     r1, r1, #15                 @ r1<- A
   8914     cmp     r9, #0                      @ check object for null
   8915     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8916     beq     common_errNullObject        @ object was null
   8917     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8918     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8919     @ no-op                             @ releasing store
   8920     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8921     GOTO_OPCODE(ip)                     @ jump to next instruction
   8922 
   8923 /* continuation for OP_IPUT_WIDE */
   8924 
   8925     /*
   8926      * Currently:
   8927      *  r0 holds resolved field
   8928      *  r9 holds object
   8929      */
   8930 .LOP_IPUT_WIDE_finish:
   8931     mov     r2, rINST, lsr #8           @ r2<- A+
   8932     cmp     r9, #0                      @ check object for null
   8933     and     r2, r2, #15                 @ r2<- A
   8934     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8935     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
   8936     beq     common_errNullObject        @ object was null
   8937     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8938     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
   8939     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   8940     add     r2, r9, r3                  @ r2<- object + byte offset
   8941     .if 0
   8942     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   8943     .else
   8944     stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
   8945     .endif
   8946     GOTO_OPCODE(r10)                    @ jump to next instruction
   8947 
   8948 /* continuation for OP_IPUT_OBJECT */
   8949 
   8950     /*
   8951      * Currently:
   8952      *  r0 holds resolved field
   8953      *  r9 holds object
   8954      */
   8955 .LOP_IPUT_OBJECT_finish:
   8956     @bl      common_squeak0
   8957     mov     r1, rINST, lsr #8           @ r1<- A+
   8958     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8959     and     r1, r1, #15                 @ r1<- A
   8960     cmp     r9, #0                      @ check object for null
   8961     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8962     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   8963     beq     common_errNullObject        @ object was null
   8964     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8965     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8966     @ no-op                             @ releasing store
   8967     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
   8968     cmp     r0, #0                      @ stored a null reference?
   8969     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
   8970     GOTO_OPCODE(ip)                     @ jump to next instruction
   8971 
   8972 /* continuation for OP_IPUT_BOOLEAN */
   8973 
   8974     /*
   8975      * Currently:
   8976      *  r0 holds resolved field
   8977      *  r9 holds object
   8978      */
   8979 .LOP_IPUT_BOOLEAN_finish:
   8980     @bl      common_squeak1
   8981     mov     r1, rINST, lsr #8           @ r1<- A+
   8982     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   8983     and     r1, r1, #15                 @ r1<- A
   8984     cmp     r9, #0                      @ check object for null
   8985     GET_VREG(r0, r1)                    @ r0<- fp[A]
   8986     beq     common_errNullObject        @ object was null
   8987     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   8988     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   8989     @ no-op                             @ releasing store
   8990     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   8991     GOTO_OPCODE(ip)                     @ jump to next instruction
   8992 
   8993 /* continuation for OP_IPUT_BYTE */
   8994 
   8995     /*
   8996      * Currently:
   8997      *  r0 holds resolved field
   8998      *  r9 holds object
   8999      */
   9000 .LOP_IPUT_BYTE_finish:
   9001     @bl      common_squeak2
   9002     mov     r1, rINST, lsr #8           @ r1<- A+
   9003     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9004     and     r1, r1, #15                 @ r1<- A
   9005     cmp     r9, #0                      @ check object for null
   9006     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9007     beq     common_errNullObject        @ object was null
   9008     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9009     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9010     @ no-op                             @ releasing store
   9011     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   9012     GOTO_OPCODE(ip)                     @ jump to next instruction
   9013 
   9014 /* continuation for OP_IPUT_CHAR */
   9015 
   9016     /*
   9017      * Currently:
   9018      *  r0 holds resolved field
   9019      *  r9 holds object
   9020      */
   9021 .LOP_IPUT_CHAR_finish:
   9022     @bl      common_squeak3
   9023     mov     r1, rINST, lsr #8           @ r1<- A+
   9024     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9025     and     r1, r1, #15                 @ r1<- A
   9026     cmp     r9, #0                      @ check object for null
   9027     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9028     beq     common_errNullObject        @ object was null
   9029     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9030     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9031     @ no-op                             @ releasing store
   9032     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   9033     GOTO_OPCODE(ip)                     @ jump to next instruction
   9034 
   9035 /* continuation for OP_IPUT_SHORT */
   9036 
   9037     /*
   9038      * Currently:
   9039      *  r0 holds resolved field
   9040      *  r9 holds object
   9041      */
   9042 .LOP_IPUT_SHORT_finish:
   9043     @bl      common_squeak4
   9044     mov     r1, rINST, lsr #8           @ r1<- A+
   9045     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9046     and     r1, r1, #15                 @ r1<- A
   9047     cmp     r9, #0                      @ check object for null
   9048     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9049     beq     common_errNullObject        @ object was null
   9050     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9051     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9052     @ no-op                             @ releasing store
   9053     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   9054     GOTO_OPCODE(ip)                     @ jump to next instruction
   9055 
   9056 /* continuation for OP_SGET */
   9057 
   9058     /*
   9059      * Continuation if the field has not yet been resolved.
   9060      *  r1: BBBB field ref
   9061      */
   9062 .LOP_SGET_resolve:
   9063     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9064     EXPORT_PC()                         @ resolve() could throw, so export now
   9065     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9066     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9067     cmp     r0, #0                      @ success?
   9068     bne     .LOP_SGET_finish          @ yes, finish
   9069     b       common_exceptionThrown      @ no, handle exception
   9070 
   9071 /* continuation for OP_SGET_WIDE */
   9072 
   9073     /*
   9074      * Continuation if the field has not yet been resolved.
   9075      *  r1: BBBB field ref
   9076      *
   9077      * Returns StaticField pointer in r0.
   9078      */
   9079 .LOP_SGET_WIDE_resolve:
   9080     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9081     EXPORT_PC()                         @ resolve() could throw, so export now
   9082     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9083     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9084     cmp     r0, #0                      @ success?
   9085     bne     .LOP_SGET_WIDE_finish          @ yes, finish
   9086     b       common_exceptionThrown      @ no, handle exception
   9087 
   9088 /* continuation for OP_SGET_OBJECT */
   9089 
   9090     /*
   9091      * Continuation if the field has not yet been resolved.
   9092      *  r1: BBBB field ref
   9093      */
   9094 .LOP_SGET_OBJECT_resolve:
   9095     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9096     EXPORT_PC()                         @ resolve() could throw, so export now
   9097     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9098     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9099     cmp     r0, #0                      @ success?
   9100     bne     .LOP_SGET_OBJECT_finish          @ yes, finish
   9101     b       common_exceptionThrown      @ no, handle exception
   9102 
   9103 /* continuation for OP_SGET_BOOLEAN */
   9104 
   9105     /*
   9106      * Continuation if the field has not yet been resolved.
   9107      *  r1: BBBB field ref
   9108      */
   9109 .LOP_SGET_BOOLEAN_resolve:
   9110     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9111     EXPORT_PC()                         @ resolve() could throw, so export now
   9112     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9113     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9114     cmp     r0, #0                      @ success?
   9115     bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
   9116     b       common_exceptionThrown      @ no, handle exception
   9117 
   9118 /* continuation for OP_SGET_BYTE */
   9119 
   9120     /*
   9121      * Continuation if the field has not yet been resolved.
   9122      *  r1: BBBB field ref
   9123      */
   9124 .LOP_SGET_BYTE_resolve:
   9125     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9126     EXPORT_PC()                         @ resolve() could throw, so export now
   9127     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9128     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9129     cmp     r0, #0                      @ success?
   9130     bne     .LOP_SGET_BYTE_finish          @ yes, finish
   9131     b       common_exceptionThrown      @ no, handle exception
   9132 
   9133 /* continuation for OP_SGET_CHAR */
   9134 
   9135     /*
   9136      * Continuation if the field has not yet been resolved.
   9137      *  r1: BBBB field ref
   9138      */
   9139 .LOP_SGET_CHAR_resolve:
   9140     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9141     EXPORT_PC()                         @ resolve() could throw, so export now
   9142     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9143     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9144     cmp     r0, #0                      @ success?
   9145     bne     .LOP_SGET_CHAR_finish          @ yes, finish
   9146     b       common_exceptionThrown      @ no, handle exception
   9147 
   9148 /* continuation for OP_SGET_SHORT */
   9149 
   9150     /*
   9151      * Continuation if the field has not yet been resolved.
   9152      *  r1: BBBB field ref
   9153      */
   9154 .LOP_SGET_SHORT_resolve:
   9155     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9156     EXPORT_PC()                         @ resolve() could throw, so export now
   9157     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9158     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9159     cmp     r0, #0                      @ success?
   9160     bne     .LOP_SGET_SHORT_finish          @ yes, finish
   9161     b       common_exceptionThrown      @ no, handle exception
   9162 
   9163 /* continuation for OP_SPUT */
   9164 
   9165     /*
   9166      * Continuation if the field has not yet been resolved.
   9167      *  r1: BBBB field ref
   9168      */
   9169 .LOP_SPUT_resolve:
   9170     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9171     EXPORT_PC()                         @ resolve() could throw, so export now
   9172     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9173     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9174     cmp     r0, #0                      @ success?
   9175     bne     .LOP_SPUT_finish          @ yes, finish
   9176     b       common_exceptionThrown      @ no, handle exception
   9177 
   9178 /* continuation for OP_SPUT_WIDE */
   9179 
   9180     /*
   9181      * Continuation if the field has not yet been resolved.
   9182      *  r1: BBBB field ref
   9183      *  r9: &fp[AA]
   9184      *
   9185      * Returns StaticField pointer in r2.
   9186      */
   9187 .LOP_SPUT_WIDE_resolve:
   9188     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9189     EXPORT_PC()                         @ resolve() could throw, so export now
   9190     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9191     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9192     cmp     r0, #0                      @ success?
   9193     mov     r2, r0                      @ copy to r2
   9194     bne     .LOP_SPUT_WIDE_finish          @ yes, finish
   9195     b       common_exceptionThrown      @ no, handle exception
   9196 
   9197 /* continuation for OP_SPUT_OBJECT */
   9198 .LOP_SPUT_OBJECT_finish:   @ field ptr in r0
   9199     mov     r2, rINST, lsr #8           @ r2<- AA
   9200     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9201     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   9202     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9203     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
   9204     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9205     @ no-op                             @ releasing store
   9206     str     r1, [r0, #offStaticField_value]  @ field<- vAA
   9207     cmp     r1, #0                      @ stored a null object?
   9208     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
   9209     GOTO_OPCODE(ip)                     @ jump to next instruction
   9210 
   9211 /* continuation for OP_SPUT_BOOLEAN */
   9212 
   9213     /*
   9214      * Continuation if the field has not yet been resolved.
   9215      *  r1: BBBB field ref
   9216      */
   9217 .LOP_SPUT_BOOLEAN_resolve:
   9218     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9219     EXPORT_PC()                         @ resolve() could throw, so export now
   9220     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9221     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9222     cmp     r0, #0                      @ success?
   9223     bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
   9224     b       common_exceptionThrown      @ no, handle exception
   9225 
   9226 /* continuation for OP_SPUT_BYTE */
   9227 
   9228     /*
   9229      * Continuation if the field has not yet been resolved.
   9230      *  r1: BBBB field ref
   9231      */
   9232 .LOP_SPUT_BYTE_resolve:
   9233     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9234     EXPORT_PC()                         @ resolve() could throw, so export now
   9235     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9236     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9237     cmp     r0, #0                      @ success?
   9238     bne     .LOP_SPUT_BYTE_finish          @ yes, finish
   9239     b       common_exceptionThrown      @ no, handle exception
   9240 
   9241 /* continuation for OP_SPUT_CHAR */
   9242 
   9243     /*
   9244      * Continuation if the field has not yet been resolved.
   9245      *  r1: BBBB field ref
   9246      */
   9247 .LOP_SPUT_CHAR_resolve:
   9248     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9249     EXPORT_PC()                         @ resolve() could throw, so export now
   9250     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9251     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9252     cmp     r0, #0                      @ success?
   9253     bne     .LOP_SPUT_CHAR_finish          @ yes, finish
   9254     b       common_exceptionThrown      @ no, handle exception
   9255 
   9256 /* continuation for OP_SPUT_SHORT */
   9257 
   9258     /*
   9259      * Continuation if the field has not yet been resolved.
   9260      *  r1: BBBB field ref
   9261      */
   9262 .LOP_SPUT_SHORT_resolve:
   9263     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9264     EXPORT_PC()                         @ resolve() could throw, so export now
   9265     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9266     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9267     cmp     r0, #0                      @ success?
   9268     bne     .LOP_SPUT_SHORT_finish          @ yes, finish
   9269     b       common_exceptionThrown      @ no, handle exception
   9270 
   9271 /* continuation for OP_INVOKE_VIRTUAL */
   9272 
   9273     /*
   9274      * At this point:
   9275      *  r0 = resolved base method
   9276      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
   9277      */
   9278 .LOP_INVOKE_VIRTUAL_continue:
   9279     GET_VREG(r1, r10)                   @ r1<- "this" ptr
   9280     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   9281     cmp     r1, #0                      @ is "this" null?
   9282     beq     common_errNullObject        @ null "this", throw exception
   9283     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
   9284     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
   9285     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
   9286     bl      common_invokeMethodNoRange @ continue on
   9287 
   9288 /* continuation for OP_INVOKE_SUPER */
   9289 
   9290     /*
   9291      * At this point:
   9292      *  r0 = resolved base method
   9293      *  r9 = method->clazz
   9294      */
   9295 .LOP_INVOKE_SUPER_continue:
   9296     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
   9297     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   9298     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
   9299     EXPORT_PC()                         @ must export for invoke
   9300     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
   9301     bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
   9302     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
   9303     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
   9304     bl      common_invokeMethodNoRange @ continue on
   9305 
   9306 .LOP_INVOKE_SUPER_resolve:
   9307     mov     r0, r9                      @ r0<- method->clazz
   9308     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   9309     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   9310     cmp     r0, #0                      @ got null?
   9311     bne     .LOP_INVOKE_SUPER_continue        @ no, continue
   9312     b       common_exceptionThrown      @ yes, handle exception
   9313 
   9314     /*
   9315      * Throw a NoSuchMethodError with the method name as the message.
   9316      *  r0 = resolved base method
   9317      */
   9318 .LOP_INVOKE_SUPER_nsm:
   9319     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
   9320     b       common_errNoSuchMethod
   9321 
   9322 /* continuation for OP_INVOKE_DIRECT */
   9323 
   9324     /*
   9325      * On entry:
   9326      *  r1 = reference (BBBB or CCCC)
   9327      *  r10 = "this" register
   9328      */
   9329 .LOP_INVOKE_DIRECT_resolve:
   9330     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   9331     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   9332     mov     r2, #METHOD_DIRECT          @ resolver method type
   9333     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   9334     cmp     r0, #0                      @ got null?
   9335     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
   9336     bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
   9337     b       common_exceptionThrown      @ yes, handle exception
   9338 
   9339 /* continuation for OP_INVOKE_VIRTUAL_RANGE */
   9340 
   9341     /*
   9342      * At this point:
   9343      *  r0 = resolved base method
   9344      *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
   9345      */
   9346 .LOP_INVOKE_VIRTUAL_RANGE_continue:
   9347     GET_VREG(r1, r10)                   @ r1<- "this" ptr
   9348     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   9349     cmp     r1, #0                      @ is "this" null?
   9350     beq     common_errNullObject        @ null "this", throw exception
   9351     ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
   9352     ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
   9353     ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
   9354     bl      common_invokeMethodRange @ continue on
   9355 
   9356 /* continuation for OP_INVOKE_SUPER_RANGE */
   9357 
   9358     /*
   9359      * At this point:
   9360      *  r0 = resolved base method
   9361      *  r9 = method->clazz
   9362      */
   9363 .LOP_INVOKE_SUPER_RANGE_continue:
   9364     ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
   9365     ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
   9366     ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
   9367     EXPORT_PC()                         @ must export for invoke
   9368     cmp     r2, r3                      @ compare (methodIndex, vtableCount)
   9369     bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
   9370     ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
   9371     ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
   9372     bl      common_invokeMethodRange @ continue on
   9373 
   9374 .LOP_INVOKE_SUPER_RANGE_resolve:
   9375     mov     r0, r9                      @ r0<- method->clazz
   9376     mov     r2, #METHOD_VIRTUAL         @ resolver method type
   9377     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   9378     cmp     r0, #0                      @ got null?
   9379     bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
   9380     b       common_exceptionThrown      @ yes, handle exception
   9381 
   9382     /*
   9383      * Throw a NoSuchMethodError with the method name as the message.
   9384      *  r0 = resolved base method
   9385      */
   9386 .LOP_INVOKE_SUPER_RANGE_nsm:
   9387     ldr     r1, [r0, #offMethod_name]   @ r1<- method name
   9388     b       common_errNoSuchMethod
   9389 
   9390 /* continuation for OP_INVOKE_DIRECT_RANGE */
   9391 
   9392     /*
   9393      * On entry:
   9394      *  r1 = reference (BBBB or CCCC)
   9395      *  r10 = "this" register
   9396      */
   9397 .LOP_INVOKE_DIRECT_RANGE_resolve:
   9398     ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
   9399     ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
   9400     mov     r2, #METHOD_DIRECT          @ resolver method type
   9401     bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
   9402     cmp     r0, #0                      @ got null?
   9403     GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
   9404     bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
   9405     b       common_exceptionThrown      @ yes, handle exception
   9406 
   9407 /* continuation for OP_FLOAT_TO_LONG */
   9408 /*
   9409  * Convert the float in r0 to a long in r0/r1.
   9410  *
   9411  * We have to clip values to long min/max per the specification.  The
   9412  * expected common case is a "reasonable" value that converts directly
   9413  * to modest integer.  The EABI convert function isn't doing this for us.
   9414  */
   9415 f2l_doconv:
   9416     stmfd   sp!, {r4, lr}
   9417     mov     r1, #0x5f000000             @ (float)maxlong
   9418     mov     r4, r0
   9419     bl      __aeabi_fcmpge              @ is arg >= maxlong?
   9420     cmp     r0, #0                      @ nonzero == yes
   9421     mvnne   r0, #0                      @ return maxlong (7fffffff)
   9422     mvnne   r1, #0x80000000
   9423     ldmnefd sp!, {r4, pc}
   9424 
   9425     mov     r0, r4                      @ recover arg
   9426     mov     r1, #0xdf000000             @ (float)minlong
   9427     bl      __aeabi_fcmple              @ is arg <= minlong?
   9428     cmp     r0, #0                      @ nonzero == yes
   9429     movne   r0, #0                      @ return minlong (80000000)
   9430     movne   r1, #0x80000000
   9431     ldmnefd sp!, {r4, pc}
   9432 
   9433     mov     r0, r4                      @ recover arg
   9434     mov     r1, r4
   9435     bl      __aeabi_fcmpeq              @ is arg == self?
   9436     cmp     r0, #0                      @ zero == no
   9437     moveq   r1, #0                      @ return zero for NaN
   9438     ldmeqfd sp!, {r4, pc}
   9439 
   9440     mov     r0, r4                      @ recover arg
   9441     bl      __aeabi_f2lz                @ convert float to long
   9442     ldmfd   sp!, {r4, pc}
   9443 
   9444 /* continuation for OP_DOUBLE_TO_LONG */
   9445 /*
   9446  * Convert the double in r0/r1 to a long in r0/r1.
   9447  *
   9448  * We have to clip values to long min/max per the specification.  The
   9449  * expected common case is a "reasonable" value that converts directly
   9450  * to modest integer.  The EABI convert function isn't doing this for us.
   9451  */
   9452 d2l_doconv:
   9453     stmfd   sp!, {r4, r5, lr}           @ save regs
   9454     mov     r3, #0x43000000             @ maxlong, as a double (high word)
   9455     add     r3, #0x00e00000             @  0x43e00000
   9456     mov     r2, #0                      @ maxlong, as a double (low word)
   9457     sub     sp, sp, #4                  @ align for EABI
   9458     mov     r4, r0                      @ save a copy of r0
   9459     mov     r5, r1                      @  and r1
   9460     bl      __aeabi_dcmpge              @ is arg >= maxlong?
   9461     cmp     r0, #0                      @ nonzero == yes
   9462     mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
   9463     mvnne   r1, #0x80000000
   9464     bne     1f
   9465 
   9466     mov     r0, r4                      @ recover arg
   9467     mov     r1, r5
   9468     mov     r3, #0xc3000000             @ minlong, as a double (high word)
   9469     add     r3, #0x00e00000             @  0xc3e00000
   9470     mov     r2, #0                      @ minlong, as a double (low word)
   9471     bl      __aeabi_dcmple              @ is arg <= minlong?
   9472     cmp     r0, #0                      @ nonzero == yes
   9473     movne   r0, #0                      @ return minlong (8000000000000000)
   9474     movne   r1, #0x80000000
   9475     bne     1f
   9476 
   9477     mov     r0, r4                      @ recover arg
   9478     mov     r1, r5
   9479     mov     r2, r4                      @ compare against self
   9480     mov     r3, r5
   9481     bl      __aeabi_dcmpeq              @ is arg == self?
   9482     cmp     r0, #0                      @ zero == no
   9483     moveq   r1, #0                      @ return zero for NaN
   9484     beq     1f
   9485 
   9486     mov     r0, r4                      @ recover arg
   9487     mov     r1, r5
   9488     bl      __aeabi_d2lz                @ convert double to long
   9489 
   9490 1:
   9491     add     sp, sp, #4
   9492     ldmfd   sp!, {r4, r5, pc}
   9493 
   9494 /* continuation for OP_MUL_LONG */
   9495 
   9496 .LOP_MUL_LONG_finish:
   9497     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9498     stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
   9499     GOTO_OPCODE(ip)                     @ jump to next instruction
   9500 
   9501 /* continuation for OP_SHL_LONG */
   9502 
   9503 .LOP_SHL_LONG_finish:
   9504     mov     r0, r0, asl r2              @  r0<- r0 << r2
   9505     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9506     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9507     GOTO_OPCODE(ip)                     @ jump to next instruction
   9508 
   9509 /* continuation for OP_SHR_LONG */
   9510 
   9511 .LOP_SHR_LONG_finish:
   9512     mov     r1, r1, asr r2              @  r1<- r1 >> r2
   9513     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9514     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9515     GOTO_OPCODE(ip)                     @ jump to next instruction
   9516 
   9517 /* continuation for OP_USHR_LONG */
   9518 
   9519 .LOP_USHR_LONG_finish:
   9520     mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
   9521     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9522     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9523     GOTO_OPCODE(ip)                     @ jump to next instruction
   9524 
   9525 /* continuation for OP_SHL_LONG_2ADDR */
   9526 
   9527 .LOP_SHL_LONG_2ADDR_finish:
   9528     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9529     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9530     GOTO_OPCODE(ip)                     @ jump to next instruction
   9531 
   9532 /* continuation for OP_SHR_LONG_2ADDR */
   9533 
   9534 .LOP_SHR_LONG_2ADDR_finish:
   9535     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9536     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9537     GOTO_OPCODE(ip)                     @ jump to next instruction
   9538 
   9539 /* continuation for OP_USHR_LONG_2ADDR */
   9540 
   9541 .LOP_USHR_LONG_2ADDR_finish:
   9542     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9543     stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
   9544     GOTO_OPCODE(ip)                     @ jump to next instruction
   9545 
   9546 /* continuation for OP_IGET_VOLATILE */
   9547 
   9548     /*
   9549      * Currently:
   9550      *  r0 holds resolved field
   9551      *  r9 holds object
   9552      */
   9553 .LOP_IGET_VOLATILE_finish:
   9554     @bl      common_squeak0
   9555     cmp     r9, #0                      @ check object for null
   9556     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9557     beq     common_errNullObject        @ object was null
   9558     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   9559     SMP_DMB                            @ acquiring load
   9560     mov     r2, rINST, lsr #8           @ r2<- A+
   9561     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9562     and     r2, r2, #15                 @ r2<- A
   9563     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9564     SET_VREG(r0, r2)                    @ fp[A]<- r0
   9565     GOTO_OPCODE(ip)                     @ jump to next instruction
   9566 
   9567 /* continuation for OP_IPUT_VOLATILE */
   9568 
   9569     /*
   9570      * Currently:
   9571      *  r0 holds resolved field
   9572      *  r9 holds object
   9573      */
   9574 .LOP_IPUT_VOLATILE_finish:
   9575     @bl      common_squeak0
   9576     mov     r1, rINST, lsr #8           @ r1<- A+
   9577     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9578     and     r1, r1, #15                 @ r1<- A
   9579     cmp     r9, #0                      @ check object for null
   9580     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9581     beq     common_errNullObject        @ object was null
   9582     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9583     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9584     SMP_DMB                            @ releasing store
   9585     str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
   9586     GOTO_OPCODE(ip)                     @ jump to next instruction
   9587 
   9588 /* continuation for OP_SGET_VOLATILE */
   9589 
   9590     /*
   9591      * Continuation if the field has not yet been resolved.
   9592      *  r1: BBBB field ref
   9593      */
   9594 .LOP_SGET_VOLATILE_resolve:
   9595     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9596     EXPORT_PC()                         @ resolve() could throw, so export now
   9597     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9598     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9599     cmp     r0, #0                      @ success?
   9600     bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
   9601     b       common_exceptionThrown      @ no, handle exception
   9602 
   9603 /* continuation for OP_SPUT_VOLATILE */
   9604 
   9605     /*
   9606      * Continuation if the field has not yet been resolved.
   9607      *  r1: BBBB field ref
   9608      */
   9609 .LOP_SPUT_VOLATILE_resolve:
   9610     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9611     EXPORT_PC()                         @ resolve() could throw, so export now
   9612     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9613     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9614     cmp     r0, #0                      @ success?
   9615     bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
   9616     b       common_exceptionThrown      @ no, handle exception
   9617 
   9618 /* continuation for OP_IGET_OBJECT_VOLATILE */
   9619 
   9620     /*
   9621      * Currently:
   9622      *  r0 holds resolved field
   9623      *  r9 holds object
   9624      */
   9625 .LOP_IGET_OBJECT_VOLATILE_finish:
   9626     @bl      common_squeak0
   9627     cmp     r9, #0                      @ check object for null
   9628     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9629     beq     common_errNullObject        @ object was null
   9630     ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
   9631     SMP_DMB                            @ acquiring load
   9632     mov     r2, rINST, lsr #8           @ r2<- A+
   9633     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9634     and     r2, r2, #15                 @ r2<- A
   9635     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9636     SET_VREG(r0, r2)                    @ fp[A]<- r0
   9637     GOTO_OPCODE(ip)                     @ jump to next instruction
   9638 
   9639 /* continuation for OP_IGET_WIDE_VOLATILE */
   9640 
   9641     /*
   9642      * Currently:
   9643      *  r0 holds resolved field
   9644      *  r9 holds object
   9645      */
   9646 .LOP_IGET_WIDE_VOLATILE_finish:
   9647     cmp     r9, #0                      @ check object for null
   9648     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9649     beq     common_errNullObject        @ object was null
   9650     .if 1
   9651     add     r0, r9, r3                  @ r0<- address of field
   9652     bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
   9653     .else
   9654     add     r9, r9, r3                  @ r9<- obj + field offset
   9655     ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
   9656     .endif
   9657     mov     r2, rINST, lsr #8           @ r2<- A+
   9658     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9659     and     r2, r2, #15                 @ r2<- A
   9660     add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
   9661     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9662     stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
   9663     GOTO_OPCODE(ip)                     @ jump to next instruction
   9664 
   9665 /* continuation for OP_IPUT_WIDE_VOLATILE */
   9666 
   9667     /*
   9668      * Currently:
   9669      *  r0 holds resolved field
   9670      *  r9 holds object
   9671      */
   9672 .LOP_IPUT_WIDE_VOLATILE_finish:
   9673     mov     r2, rINST, lsr #8           @ r2<- A+
   9674     cmp     r9, #0                      @ check object for null
   9675     and     r2, r2, #15                 @ r2<- A
   9676     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9677     add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
   9678     beq     common_errNullObject        @ object was null
   9679     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9680     ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
   9681     GET_INST_OPCODE(r10)                @ extract opcode from rINST
   9682     add     r2, r9, r3                  @ r2<- object + byte offset
   9683     .if 1
   9684     bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
   9685     .else
   9686     stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
   9687     .endif
   9688     GOTO_OPCODE(r10)                    @ jump to next instruction
   9689 
   9690 /* continuation for OP_SGET_WIDE_VOLATILE */
   9691 
   9692     /*
   9693      * Continuation if the field has not yet been resolved.
   9694      *  r1: BBBB field ref
   9695      *
   9696      * Returns StaticField pointer in r0.
   9697      */
   9698 .LOP_SGET_WIDE_VOLATILE_resolve:
   9699     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9700     EXPORT_PC()                         @ resolve() could throw, so export now
   9701     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9702     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9703     cmp     r0, #0                      @ success?
   9704     bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
   9705     b       common_exceptionThrown      @ no, handle exception
   9706 
   9707 /* continuation for OP_SPUT_WIDE_VOLATILE */
   9708 
   9709     /*
   9710      * Continuation if the field has not yet been resolved.
   9711      *  r1: BBBB field ref
   9712      *  r9: &fp[AA]
   9713      *
   9714      * Returns StaticField pointer in r2.
   9715      */
   9716 .LOP_SPUT_WIDE_VOLATILE_resolve:
   9717     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9718     EXPORT_PC()                         @ resolve() could throw, so export now
   9719     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9720     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9721     cmp     r0, #0                      @ success?
   9722     mov     r2, r0                      @ copy to r2
   9723     bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
   9724     b       common_exceptionThrown      @ no, handle exception
   9725 
   9726 /* continuation for OP_EXECUTE_INLINE */
   9727 
   9728     /*
   9729      * Extract args, call function.
   9730      *  r0 = #of args (0-4)
   9731      *  r10 = call index
   9732      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
   9733      *
   9734      * Other ideas:
   9735      * - Use a jump table from the main piece to jump directly into the
   9736      *   AND/LDR pairs.  Costs a data load, saves a branch.
   9737      * - Have five separate pieces that do the loading, so we can work the
   9738      *   interleave a little better.  Increases code size.
   9739      */
   9740 .LOP_EXECUTE_INLINE_continue:
   9741     rsb     r0, r0, #4                  @ r0<- 4-r0
   9742     FETCH(r9, 2)                        @ r9<- FEDC
   9743     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
   9744     bl      common_abort                @ (skipped due to ARM prefetch)
   9745 4:  and     ip, r9, #0xf000             @ isolate F
   9746     ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
   9747 3:  and     ip, r9, #0x0f00             @ isolate E
   9748     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
   9749 2:  and     ip, r9, #0x00f0             @ isolate D
   9750     ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
   9751 1:  and     ip, r9, #0x000f             @ isolate C
   9752     ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
   9753 0:
   9754     ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
   9755     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
   9756     @ (not reached)
   9757 
   9758 .LOP_EXECUTE_INLINE_table:
   9759     .word   gDvmInlineOpsTable
   9760 
   9761 /* continuation for OP_EXECUTE_INLINE_RANGE */
   9762 
   9763     /*
   9764      * Extract args, call function.
   9765      *  r0 = #of args (0-4)
   9766      *  r10 = call index
   9767      *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
   9768      */
   9769 .LOP_EXECUTE_INLINE_RANGE_continue:
   9770     rsb     r0, r0, #4                  @ r0<- 4-r0
   9771     FETCH(r9, 2)                        @ r9<- CCCC
   9772     add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
   9773     bl      common_abort                @ (skipped due to ARM prefetch)
   9774 4:  add     ip, r9, #3                  @ base+3
   9775     GET_VREG(r3, ip)                    @ r3<- vBase[3]
   9776 3:  add     ip, r9, #2                  @ base+2
   9777     GET_VREG(r2, ip)                    @ r2<- vBase[2]
   9778 2:  add     ip, r9, #1                  @ base+1
   9779     GET_VREG(r1, ip)                    @ r1<- vBase[1]
   9780 1:  add     ip, r9, #0                  @ (nop)
   9781     GET_VREG(r0, ip)                    @ r0<- vBase[0]
   9782 0:
   9783     ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
   9784     LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
   9785     @ (not reached)
   9786 
   9787 .LOP_EXECUTE_INLINE_RANGE_table:
   9788     .word   gDvmInlineOpsTable
   9789 
   9790 /* continuation for OP_IPUT_OBJECT_VOLATILE */
   9791 
   9792     /*
   9793      * Currently:
   9794      *  r0 holds resolved field
   9795      *  r9 holds object
   9796      */
   9797 .LOP_IPUT_OBJECT_VOLATILE_finish:
   9798     @bl      common_squeak0
   9799     mov     r1, rINST, lsr #8           @ r1<- A+
   9800     ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
   9801     and     r1, r1, #15                 @ r1<- A
   9802     cmp     r9, #0                      @ check object for null
   9803     GET_VREG(r0, r1)                    @ r0<- fp[A]
   9804     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9805     beq     common_errNullObject        @ object was null
   9806     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9807     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9808     SMP_DMB                            @ releasing store
   9809     str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
   9810     cmp     r0, #0                      @ stored a null reference?
   9811     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
   9812     GOTO_OPCODE(ip)                     @ jump to next instruction
   9813 
   9814 /* continuation for OP_SGET_OBJECT_VOLATILE */
   9815 
   9816     /*
   9817      * Continuation if the field has not yet been resolved.
   9818      *  r1: BBBB field ref
   9819      */
   9820 .LOP_SGET_OBJECT_VOLATILE_resolve:
   9821     ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
   9822     EXPORT_PC()                         @ resolve() could throw, so export now
   9823     ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
   9824     bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
   9825     cmp     r0, #0                      @ success?
   9826     bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
   9827     b       common_exceptionThrown      @ no, handle exception
   9828 
   9829 /* continuation for OP_SPUT_OBJECT_VOLATILE */
   9830 .LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
   9831     mov     r2, rINST, lsr #8           @ r2<- AA
   9832     FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
   9833     GET_VREG(r1, r2)                    @ r1<- fp[AA]
   9834     ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
   9835     ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
   9836     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   9837     SMP_DMB                            @ releasing store
   9838     str     r1, [r0, #offStaticField_value]  @ field<- vAA
   9839     cmp     r1, #0                      @ stored a null object?
   9840     strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
   9841     GOTO_OPCODE(ip)                     @ jump to next instruction
   9842 
   9843     .size   dvmAsmSisterStart, .-dvmAsmSisterStart
   9844     .global dvmAsmSisterEnd
   9845 dvmAsmSisterEnd:
   9846 
   9847 /* File: armv5te/footer.S */
   9848 
   9849 /*
   9850  * ===========================================================================
   9851  *  Common subroutines and data
   9852  * ===========================================================================
   9853  */
   9854 
   9855 
   9856 
   9857     .text
   9858     .align  2
   9859 
   9860 #if defined(WITH_JIT)
   9861 #if defined(WITH_SELF_VERIFICATION)
   9862     .global dvmJitToInterpPunt
   9863 dvmJitToInterpPunt:
   9864     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9865     mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
   9866     mov    r3, #0
   9867     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9868     b      jitSVShadowRunEnd            @ doesn't return
   9869 
   9870     .global dvmJitToInterpSingleStep
   9871 dvmJitToInterpSingleStep:
   9872     str    lr,[rGLUE,#offGlue_jitResumeNPC]
   9873     str    r1,[rGLUE,#offGlue_jitResumeDPC]
   9874     mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
   9875     b      jitSVShadowRunEnd            @ doesn't return
   9876 
   9877     .global dvmJitToInterpNoChainNoProfile
   9878 dvmJitToInterpNoChainNoProfile:
   9879     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9880     mov    r0,rPC                       @ pass our target PC
   9881     mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
   9882     mov    r3, #0                       @ 0 means !inJitCodeCache
   9883     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
   9884     b      jitSVShadowRunEnd            @ doesn't return
   9885 
   9886     .global dvmJitToInterpTraceSelectNoChain
   9887 dvmJitToInterpTraceSelectNoChain:
   9888     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9889     mov    r0,rPC                       @ pass our target PC
   9890     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
   9891     mov    r3, #0                       @ 0 means !inJitCodeCache
   9892     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9893     b      jitSVShadowRunEnd            @ doesn't return
   9894 
   9895     .global dvmJitToInterpTraceSelect
   9896 dvmJitToInterpTraceSelect:
   9897     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9898     ldr    r0,[lr, #-1]                 @ pass our target PC
   9899     mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
   9900     mov    r3, #0                       @ 0 means !inJitCodeCache
   9901     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9902     b      jitSVShadowRunEnd            @ doesn't return
   9903 
   9904     .global dvmJitToInterpBackwardBranch
   9905 dvmJitToInterpBackwardBranch:
   9906     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9907     ldr    r0,[lr, #-1]                 @ pass our target PC
   9908     mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
   9909     mov    r3, #0                       @ 0 means !inJitCodeCache
   9910     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9911     b      jitSVShadowRunEnd            @ doesn't return
   9912 
   9913     .global dvmJitToInterpNormal
   9914 dvmJitToInterpNormal:
   9915     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9916     ldr    r0,[lr, #-1]                 @ pass our target PC
   9917     mov    r2,#kSVSNormal               @ r2<- interpreter entry point
   9918     mov    r3, #0                       @ 0 means !inJitCodeCache
   9919     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9920     b      jitSVShadowRunEnd            @ doesn't return
   9921 
   9922     .global dvmJitToInterpNoChain
   9923 dvmJitToInterpNoChain:
   9924     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9925     mov    r0,rPC                       @ pass our target PC
   9926     mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
   9927     mov    r3, #0                       @ 0 means !inJitCodeCache
   9928     str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9929     b      jitSVShadowRunEnd            @ doesn't return
   9930 #else
   9931 /*
   9932  * Return from the translation cache to the interpreter when the compiler is
   9933  * having issues translating/executing a Dalvik instruction. We have to skip
   9934  * the code cache lookup otherwise it is possible to indefinitely bouce
   9935  * between the interpreter and the code cache if the instruction that fails
   9936  * to be compiled happens to be at a trace start.
   9937  */
   9938     .global dvmJitToInterpPunt
   9939 dvmJitToInterpPunt:
   9940     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9941     mov    rPC, r0
   9942 #if defined(WITH_JIT_TUNING)
   9943     mov    r0,lr
   9944     bl     dvmBumpPunt;
   9945 #endif
   9946     EXPORT_PC()
   9947     mov    r0, #0
   9948     str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
   9949     adrl   rIBASE, dvmAsmInstructionStart
   9950     FETCH_INST()
   9951     GET_INST_OPCODE(ip)
   9952     GOTO_OPCODE(ip)
   9953 
   9954 /*
   9955  * Return to the interpreter to handle a single instruction.
   9956  * On entry:
   9957  *    r0 <= PC
   9958  *    r1 <= PC of resume instruction
   9959  *    lr <= resume point in translation
   9960  */
   9961     .global dvmJitToInterpSingleStep
   9962 dvmJitToInterpSingleStep:
   9963     str    lr,[rGLUE,#offGlue_jitResumeNPC]
   9964     str    r1,[rGLUE,#offGlue_jitResumeDPC]
   9965     mov    r1,#kInterpEntryInstr
   9966     @ enum is 4 byte in aapcs-EABI
   9967     str    r1, [rGLUE, #offGlue_entryPoint]
   9968     mov    rPC,r0
   9969     EXPORT_PC()
   9970 
   9971     adrl   rIBASE, dvmAsmInstructionStart
   9972     mov    r2,#kJitSingleStep     @ Ask for single step and then revert
   9973     str    r2,[rGLUE,#offGlue_jitState]
   9974     mov    r1,#1                  @ set changeInterp to bail to debug interp
   9975     b      common_gotoBail
   9976 
   9977 /*
   9978  * Return from the translation cache and immediately request
   9979  * a translation for the exit target.  Commonly used for callees.
   9980  */
   9981     .global dvmJitToInterpTraceSelectNoChain
   9982 dvmJitToInterpTraceSelectNoChain:
   9983 #if defined(WITH_JIT_TUNING)
   9984     bl     dvmBumpNoChain
   9985 #endif
   9986     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   9987     mov    r0,rPC
   9988     bl     dvmJitGetCodeAddr        @ Is there a translation?
   9989     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   9990     mov    r1, rPC                  @ arg1 of translation may need this
   9991     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   9992     cmp    r0,#0                    @ !0 means translation exists
   9993     bxne   r0                       @ continue native execution if so
   9994     b      2f                       @ branch over to use the interpreter
   9995 
   9996 /*
   9997  * Return from the translation cache and immediately request
   9998  * a translation for the exit target.  Commonly used following
   9999  * invokes.
   10000  */
   10001     .global dvmJitToInterpTraceSelect
   10002 dvmJitToInterpTraceSelect:
   10003     ldr    rPC,[lr, #-1]           @ get our target PC
   10004     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   10005     add    rINST,lr,#-5            @ save start of chain branch
   10006     add    rINST, #-4              @  .. which is 9 bytes back
   10007     mov    r0,rPC
   10008     bl     dvmJitGetCodeAddr       @ Is there a translation?
   10009     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   10010     cmp    r0,#0
   10011     beq    2f
   10012     mov    r1,rINST
   10013     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
   10014     mov    r1, rPC                  @ arg1 of translation may need this
   10015     mov    lr, #0                   @ in case target is HANDLER_INTERPRET
   10016     cmp    r0,#0                    @ successful chain?
   10017     bxne   r0                       @ continue native execution
   10018     b      toInterpreter            @ didn't chain - resume with interpreter
   10019 
   10020 /* No translation, so request one if profiling isn't disabled*/
   10021 2:
   10022     adrl   rIBASE, dvmAsmInstructionStart
   10023     GET_JIT_PROF_TABLE(r0)
   10024     FETCH_INST()
   10025     cmp    r0, #0
   10026     movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
   10027     bne    common_selectTrace
   10028     GET_INST_OPCODE(ip)
   10029     GOTO_OPCODE(ip)
   10030 
   10031 /*
   10032  * Return from the translation cache to the interpreter.
   10033  * The return was done with a BLX from thumb mode, and
   10034  * the following 32-bit word contains the target rPC value.
   10035  * Note that lr (r14) will have its low-order bit set to denote
   10036  * its thumb-mode origin.
   10037  *
   10038  * We'll need to stash our lr origin away, recover the new
   10039  * target and then check to see if there is a translation available
   10040  * for our new target.  If so, we do a translation chain and
   10041  * go back to native execution.  Otherwise, it's back to the
   10042  * interpreter (after treating this entry as a potential
   10043  * trace start).
   10044  */
   10045     .global dvmJitToInterpNormal
   10046 dvmJitToInterpNormal:
   10047     ldr    rPC,[lr, #-1]           @ get our target PC
   10048     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   10049     add    rINST,lr,#-5            @ save start of chain branch
   10050     add    rINST,#-4               @ .. which is 9 bytes back
   10051 #if defined(WITH_JIT_TUNING)
   10052     bl     dvmBumpNormal
   10053 #endif
   10054     mov    r0,rPC
   10055     bl     dvmJitGetCodeAddr        @ Is there a translation?
   10056     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   10057     cmp    r0,#0
   10058     beq    toInterpreter            @ go if not, otherwise do chain
   10059     mov    r1,rINST
   10060     bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
   10061     mov    r1, rPC                  @ arg1 of translation may need this
   10062     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   10063     cmp    r0,#0                    @ successful chain?
   10064     bxne   r0                       @ continue native execution
   10065     b      toInterpreter            @ didn't chain - resume with interpreter
   10066 
   10067 /*
   10068  * Return from the translation cache to the interpreter to do method invocation.
   10069  * Check if translation exists for the callee, but don't chain to it.
   10070  */
   10071     .global dvmJitToInterpNoChainNoProfile
   10072 dvmJitToInterpNoChainNoProfile:
   10073 #if defined(WITH_JIT_TUNING)
   10074     bl     dvmBumpNoChain
   10075 #endif
   10076     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   10077     mov    r0,rPC
   10078     bl     dvmJitGetCodeAddr        @ Is there a translation?
   10079     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   10080     mov    r1, rPC                  @ arg1 of translation may need this
   10081     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   10082     cmp    r0,#0
   10083     bxne   r0                       @ continue native execution if so
   10084     EXPORT_PC()
   10085     adrl   rIBASE, dvmAsmInstructionStart
   10086     FETCH_INST()
   10087     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10088     GOTO_OPCODE(ip)                     @ jump to next instruction
   10089 
   10090 /*
   10091  * Return from the translation cache to the interpreter to do method invocation.
   10092  * Check if translation exists for the callee, but don't chain to it.
   10093  */
   10094     .global dvmJitToInterpNoChain
   10095 dvmJitToInterpNoChain:
   10096 #if defined(WITH_JIT_TUNING)
   10097     bl     dvmBumpNoChain
   10098 #endif
   10099     ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
   10100     mov    r0,rPC
   10101     bl     dvmJitGetCodeAddr        @ Is there a translation?
   10102     str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   10103     mov    r1, rPC                  @ arg1 of translation may need this
   10104     mov    lr, #0                   @  in case target is HANDLER_INTERPRET
   10105     cmp    r0,#0
   10106     bxne   r0                       @ continue native execution if so
   10107 #endif
   10108 
   10109 /*
   10110  * No translation, restore interpreter regs and start interpreting.
   10111  * rGLUE & rFP were preserved in the translated code, and rPC has
   10112  * already been restored by the time we get here.  We'll need to set
   10113  * up rIBASE & rINST, and load the address of the JitTable into r0.
   10114  */
   10115 toInterpreter:
   10116     EXPORT_PC()
   10117     adrl   rIBASE, dvmAsmInstructionStart
   10118     FETCH_INST()
   10119     GET_JIT_PROF_TABLE(r0)
   10120     @ NOTE: intended fallthrough
   10121 
   10122 /*
   10123  * Common code to update potential trace start counter, and initiate
   10124  * a trace-build if appropriate.  On entry, rPC should point to the
   10125  * next instruction to execute, and rINST should be already loaded with
   10126  * the next opcode word, and r0 holds a pointer to the jit profile
   10127  * table (pJitProfTable).
   10128  */
   10129 common_testUpdateProfile:
   10130     cmp     r0,#0
   10131     GET_INST_OPCODE(ip)
   10132     GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
   10133 
   10134 common_updateProfile:
   10135     eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
   10136     lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
   10137     ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
   10138     GET_INST_OPCODE(ip)
   10139     subs    r1,r1,#1           @ decrement counter
   10140     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
   10141     GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
   10142 
   10143 /*
   10144  * Here, we switch to the debug interpreter to request
   10145  * trace selection.  First, though, check to see if there
   10146  * is already a native translation in place (and, if so,
   10147  * jump to it now).
   10148  */
   10149     GET_JIT_THRESHOLD(r1)
   10150     ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
   10151     strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
   10152     EXPORT_PC()
   10153     mov     r0,rPC
   10154     bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
   10155     str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
   10156     mov     r1, rPC                     @ arg1 of translation may need this
   10157     mov     lr, #0                      @  in case target is HANDLER_INTERPRET
   10158     cmp     r0,#0
   10159 #if !defined(WITH_SELF_VERIFICATION)
   10160     bxne    r0                          @ jump to the translation
   10161     mov     r2,#kJitTSelectRequest      @ ask for trace selection
   10162     @ fall-through to common_selectTrace
   10163 #else
   10164     moveq   r2,#kJitTSelectRequest      @ ask for trace selection
   10165     beq     common_selectTrace
   10166     /*
   10167      * At this point, we have a target translation.  However, if
   10168      * that translation is actually the interpret-only pseudo-translation
   10169      * we want to treat it the same as no translation.
   10170      */
   10171     mov     r10, r0                     @ save target
   10172     bl      dvmCompilerGetInterpretTemplate
   10173     cmp     r0, r10                     @ special case?
   10174     bne     jitSVShadowRunStart         @ set up self verification shadow space
   10175     @ Need to clear the inJitCodeCache flag
   10176     ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
   10177     mov    r3, #0                       @ 0 means not in the JIT code cache
   10178     str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
   10179     GET_INST_OPCODE(ip)
   10180     GOTO_OPCODE(ip)
   10181     /* no return */
   10182 #endif
   10183 
   10184 /*
   10185  * On entry:
   10186  *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
   10187  */
   10188 common_selectTrace:
   10189     str     r2,[rGLUE,#offGlue_jitState]
   10190     mov     r2,#kInterpEntryInstr       @ normal entry reason
   10191     str     r2,[rGLUE,#offGlue_entryPoint]
   10192     mov     r1,#1                       @ set changeInterp
   10193     b       common_gotoBail
   10194 
   10195 #if defined(WITH_SELF_VERIFICATION)
   10196 /*
   10197  * Save PC and registers to shadow memory for self verification mode
   10198  * before jumping to native translation.
   10199  * On entry:
   10200  *    rPC, rFP, rGLUE: the values that they should contain
   10201  *    r10: the address of the target translation.
   10202  */
   10203 jitSVShadowRunStart:
   10204     mov     r0,rPC                      @ r0<- program counter
   10205     mov     r1,rFP                      @ r1<- frame pointer
   10206     mov     r2,rGLUE                    @ r2<- InterpState pointer
   10207     mov     r3,r10                      @ r3<- target translation
   10208     bl      dvmSelfVerificationSaveState @ save registers to shadow space
   10209     ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
   10210     add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
   10211     bx      r10                         @ jump to the translation
   10212 
   10213 /*
   10214  * Restore PC, registers, and interpState to original values
   10215  * before jumping back to the interpreter.
   10216  */
   10217 jitSVShadowRunEnd:
   10218     mov    r1,rFP                        @ pass ending fp
   10219     bl     dvmSelfVerificationRestoreState @ restore pc and fp values
   10220     ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
   10221     ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
   10222     ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
   10223     ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
   10224     cmp    r1,#0                         @ check for punt condition
   10225     beq    1f
   10226     mov    r2,#kJitSelfVerification      @ ask for self verification
   10227     str    r2,[rGLUE,#offGlue_jitState]
   10228     mov    r2,#kInterpEntryInstr         @ normal entry reason
   10229     str    r2,[rGLUE,#offGlue_entryPoint]
   10230     mov    r1,#1                         @ set changeInterp
   10231     b      common_gotoBail
   10232 
   10233 1:                                       @ exit to interpreter without check
   10234     EXPORT_PC()
   10235     adrl   rIBASE, dvmAsmInstructionStart
   10236     FETCH_INST()
   10237     GET_INST_OPCODE(ip)
   10238     GOTO_OPCODE(ip)
   10239 #endif
   10240 
   10241 #endif
   10242 
   10243 /*
   10244  * Common code when a backward branch is taken.
   10245  *
   10246  * TODO: we could avoid a branch by just setting r0 and falling through
   10247  * into the common_periodicChecks code, and having a test on r0 at the
   10248  * end determine if we should return to the caller or update & branch to
   10249  * the next instr.
   10250  *
   10251  * On entry:
   10252  *  r9 is PC adjustment *in bytes*
   10253  */
   10254 common_backwardBranch:
   10255     mov     r0, #kInterpEntryInstr
   10256     bl      common_periodicChecks
   10257 #if defined(WITH_JIT)
   10258     GET_JIT_PROF_TABLE(r0)
   10259     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   10260     cmp     r0,#0
   10261     bne     common_updateProfile
   10262     GET_INST_OPCODE(ip)
   10263     GOTO_OPCODE(ip)
   10264 #else
   10265     FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
   10266     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10267     GOTO_OPCODE(ip)                     @ jump to next instruction
   10268 #endif
   10269 
   10270 
   10271 /*
   10272  * Need to see if the thread needs to be suspended or debugger/profiler
   10273  * activity has begun.  If so, we suspend the thread or side-exit to
   10274  * the debug interpreter as appropriate.
   10275  *
   10276  * The common case is no activity on any of these, so we want to figure
   10277  * that out quickly.  If something is up, we can then sort out what.
   10278  *
   10279  * We want to be fast if the VM was built without debugger or profiler
   10280  * support, but we also need to recognize that the system is usually
   10281  * shipped with both of these enabled.
   10282  *
   10283  * TODO: reduce this so we're just checking a single location.
   10284  *
   10285  * On entry:
   10286  *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
   10287  *  r9 is trampoline PC adjustment *in bytes*
   10288  */
   10289 common_periodicChecks:
   10290     ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
   10291 
   10292     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
   10293     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
   10294 
   10295     ldr     ip, [r3]                    @ ip<- suspendCount (int)
   10296 
   10297     cmp     r1, #0                      @ debugger enabled?
   10298     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
   10299     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
   10300     orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
   10301     orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
   10302 
   10303     bxeq    lr                          @ all zero, return
   10304 
   10305     /*
   10306      * One or more interesting events have happened.  Figure out what.
   10307      *
   10308      * If debugging or profiling are compiled in, we need to disambiguate.
   10309      *
   10310      * r0 still holds the reentry type.
   10311      */
   10312     ldr     ip, [r3]                    @ ip<- suspendCount (int)
   10313     cmp     ip, #0                      @ want suspend?
   10314     beq     1f                          @ no, must be debugger/profiler
   10315 
   10316     stmfd   sp!, {r0, lr}               @ preserve r0 and lr
   10317 #if defined(WITH_JIT)
   10318     /*
   10319      * Refresh the Jit's cached copy of profile table pointer.  This pointer
   10320      * doubles as the Jit's on/off switch.
   10321      */
   10322     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
   10323     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   10324     ldr     r3, [r3] @ r3 <- pJitProfTable
   10325     EXPORT_PC()                         @ need for precise GC
   10326     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
   10327 #else
   10328     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
   10329     EXPORT_PC()                         @ need for precise GC
   10330 #endif
   10331     bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
   10332     ldmfd   sp!, {r0, lr}               @ restore r0 and lr
   10333 
   10334     /*
   10335      * Reload the debugger/profiler enable flags.  We're checking to see
   10336      * if either of these got set while we were suspended.
   10337      *
   10338      * We can't really avoid the #ifdefs here, because the fields don't
   10339      * exist when the feature is disabled.
   10340      */
   10341     ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
   10342     cmp     r1, #0                      @ debugger enabled?
   10343     ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
   10344     ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
   10345     ldr     r2, [r2]                    @ r2<- activeProfilers (int)
   10346 
   10347     orrs    r1, r1, r2
   10348     beq     2f
   10349 
   10350 1:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
   10351     str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
   10352     add     rPC, rPC, r9                @ update rPC
   10353     mov     r1, #1                      @ "want switch" = true
   10354     b       common_gotoBail             @ side exit
   10355 
   10356 2:
   10357     bx      lr                          @ nothing to do, return
   10358 
   10359 
   10360 /*
   10361  * The equivalent of "goto bail", this calls through the "bail handler".
   10362  *
   10363  * State registers will be saved to the "glue" area before bailing.
   10364  *
   10365  * On entry:
   10366  *  r1 is "bool changeInterp", indicating if we want to switch to the
   10367  *     other interpreter or just bail all the way out
   10368  */
   10369 common_gotoBail:
   10370     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
   10371     mov     r0, rGLUE                   @ r0<- glue ptr
   10372     b       dvmMterpStdBail             @ call(glue, changeInterp)
   10373 
   10374     @add     r1, r1, #1                  @ using (boolean+1)
   10375     @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
   10376     @bl      _longjmp                    @ does not return
   10377     @bl      common_abort
   10378 
   10379 
   10380 /*
   10381  * Common code for method invocation with range.
   10382  *
   10383  * On entry:
   10384  *  r0 is "Method* methodToCall", the method we're trying to call
   10385  */
   10386 common_invokeMethodRange:
   10387 .LinvokeNewRange:
   10388     @ prepare to copy args to "outs" area of current frame
   10389     movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
   10390     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
   10391     beq     .LinvokeArgsDone            @ if no args, skip the rest
   10392     FETCH(r1, 2)                        @ r1<- CCCC
   10393 
   10394     @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
   10395     @ (very few methods have > 10 args; could unroll for common cases)
   10396     add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
   10397     sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
   10398     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
   10399 1:  ldr     r1, [r3], #4                @ val = *fp++
   10400     subs    r2, r2, #1                  @ count--
   10401     str     r1, [r10], #4               @ *outs++ = val
   10402     bne     1b                          @ ...while count != 0
   10403     ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
   10404     b       .LinvokeArgsDone
   10405 
   10406 /*
   10407  * Common code for method invocation without range.
   10408  *
   10409  * On entry:
   10410  *  r0 is "Method* methodToCall", the method we're trying to call
   10411  */
   10412 common_invokeMethodNoRange:
   10413 .LinvokeNewNoRange:
   10414     @ prepare to copy args to "outs" area of current frame
   10415     movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
   10416     SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
   10417     FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
   10418     ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
   10419     ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
   10420     beq     .LinvokeArgsDone
   10421 
   10422     @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
   10423 .LinvokeNonRange:
   10424     rsb     r2, r2, #5                  @ r2<- 5-r2
   10425     add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
   10426     bl      common_abort                @ (skipped due to ARM prefetch)
   10427 5:  and     ip, rINST, #0x0f00          @ isolate A
   10428     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
   10429     mov     r0, r0                      @ nop
   10430     str     r2, [r10, #-4]!             @ *--outs = vA
   10431 4:  and     ip, r1, #0xf000             @ isolate G
   10432     ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
   10433     mov     r0, r0                      @ nop
   10434     str     r2, [r10, #-4]!             @ *--outs = vG
   10435 3:  and     ip, r1, #0x0f00             @ isolate F
   10436     ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
   10437     mov     r0, r0                      @ nop
   10438     str     r2, [r10, #-4]!             @ *--outs = vF
   10439 2:  and     ip, r1, #0x00f0             @ isolate E
   10440     ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
   10441     mov     r0, r0                      @ nop
   10442     str     r2, [r10, #-4]!             @ *--outs = vE
   10443 1:  and     ip, r1, #0x000f             @ isolate D
   10444     ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
   10445     mov     r0, r0                      @ nop
   10446     str     r2, [r10, #-4]!             @ *--outs = vD
   10447 0:  @ fall through to .LinvokeArgsDone
   10448 
   10449 .LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
   10450     ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
   10451     ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
   10452     @ find space for the new stack frame, check for overflow
   10453     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
   10454     sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
   10455     SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
   10456 @    bl      common_dumpRegs
   10457     ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
   10458     sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
   10459     cmp     r3, r9                      @ bottom < interpStackEnd?
   10460     ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
   10461     blo     .LstackOverflow             @ yes, this frame will overflow stack
   10462 
   10463     @ set up newSaveArea
   10464 #ifdef EASY_GDB
   10465     SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
   10466     str     ip, [r10, #offStackSaveArea_prevSave]
   10467 #endif
   10468     str     rFP, [r10, #offStackSaveArea_prevFrame]
   10469     str     rPC, [r10, #offStackSaveArea_savedPc]
   10470 #if defined(WITH_JIT)
   10471     mov     r9, #0
   10472     str     r9, [r10, #offStackSaveArea_returnAddr]
   10473 #endif
   10474     str     r0, [r10, #offStackSaveArea_method]
   10475     tst     r3, #ACC_NATIVE
   10476     bne     .LinvokeNative
   10477 
   10478     /*
   10479     stmfd   sp!, {r0-r3}
   10480     bl      common_printNewline
   10481     mov     r0, rFP
   10482     mov     r1, #0
   10483     bl      dvmDumpFp
   10484     ldmfd   sp!, {r0-r3}
   10485     stmfd   sp!, {r0-r3}
   10486     mov     r0, r1
   10487     mov     r1, r10
   10488     bl      dvmDumpFp
   10489     bl      common_printNewline
   10490     ldmfd   sp!, {r0-r3}
   10491     */
   10492 
   10493     ldrh    r9, [r2]                        @ r9 <- load INST from new PC
   10494     ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
   10495     mov     rPC, r2                         @ publish new rPC
   10496     ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
   10497 
   10498     @ Update "glue" values for the new method
   10499     @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
   10500     str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
   10501     str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
   10502 #if defined(WITH_JIT)
   10503     GET_JIT_PROF_TABLE(r0)
   10504     mov     rFP, r1                         @ fp = newFp
   10505     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
   10506     mov     rINST, r9                       @ publish new rINST
   10507     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
   10508     cmp     r0,#0
   10509     bne     common_updateProfile
   10510     GOTO_OPCODE(ip)                         @ jump to next instruction
   10511 #else
   10512     mov     rFP, r1                         @ fp = newFp
   10513     GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
   10514     mov     rINST, r9                       @ publish new rINST
   10515     str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
   10516     GOTO_OPCODE(ip)                         @ jump to next instruction
   10517 #endif
   10518 
   10519 .LinvokeNative:
   10520     @ Prep for the native call
   10521     @ r0=methodToCall, r1=newFp, r10=newSaveArea
   10522     ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
   10523     ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
   10524     str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
   10525     str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
   10526     mov     r9, r3                      @ r9<- glue->self (preserve)
   10527 
   10528     mov     r2, r0                      @ r2<- methodToCall
   10529     mov     r0, r1                      @ r0<- newFp (points to args)
   10530     add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
   10531 
   10532 #ifdef ASSIST_DEBUGGER
   10533     /* insert fake function header to help gdb find the stack frame */
   10534     b       .Lskip
   10535     .type   dalvik_mterp, %function
   10536 dalvik_mterp:
   10537     .fnstart
   10538     MTERP_ENTRY1
   10539     MTERP_ENTRY2
   10540 .Lskip:
   10541 #endif
   10542 
   10543     @mov     lr, pc                      @ set return addr
   10544     @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
   10545     LDR_PC_LR "[r2, #offMethod_nativeFunc]"
   10546 
   10547 #if defined(WITH_JIT)
   10548     ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
   10549 #endif
   10550 
   10551     @ native return; r9=self, r10=newSaveArea
   10552     @ equivalent to dvmPopJniLocals
   10553     ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
   10554     ldr     r1, [r9, #offThread_exception] @ check for exception
   10555 #if defined(WITH_JIT)
   10556     ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
   10557 #endif
   10558     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
   10559     cmp     r1, #0                      @ null?
   10560     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
   10561 #if defined(WITH_JIT)
   10562     str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
   10563 #endif
   10564     bne     common_exceptionThrown      @ no, handle exception
   10565 
   10566     FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
   10567     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10568     GOTO_OPCODE(ip)                     @ jump to next instruction
   10569 
   10570 .LstackOverflow:    @ r0=methodToCall
   10571     mov     r1, r0                      @ r1<- methodToCall
   10572     ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
   10573     bl      dvmHandleStackOverflow
   10574     b       common_exceptionThrown
   10575 #ifdef ASSIST_DEBUGGER
   10576     .fnend
   10577 #endif
   10578 
   10579 
   10580     /*
   10581      * Common code for method invocation, calling through "glue code".
   10582      *
   10583      * TODO: now that we have range and non-range invoke handlers, this
   10584      *       needs to be split into two.  Maybe just create entry points
   10585      *       that set r9 and jump here?
   10586      *
   10587      * On entry:
   10588      *  r0 is "Method* methodToCall", the method we're trying to call
   10589      *  r9 is "bool methodCallRange", indicating if this is a /range variant
   10590      */
   10591      .if    0
   10592 .LinvokeOld:
   10593     sub     sp, sp, #8                  @ space for args + pad
   10594     FETCH(ip, 2)                        @ ip<- FEDC or CCCC
   10595     mov     r2, r0                      @ A2<- methodToCall
   10596     mov     r0, rGLUE                   @ A0<- glue
   10597     SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
   10598     mov     r1, r9                      @ A1<- methodCallRange
   10599     mov     r3, rINST, lsr #8           @ A3<- AA
   10600     str     ip, [sp, #0]                @ A4<- ip
   10601     bl      dvmMterp_invokeMethod       @ call the C invokeMethod
   10602     add     sp, sp, #8                  @ remove arg area
   10603     b       common_resumeAfterGlueCall  @ continue to next instruction
   10604     .endif
   10605 
   10606 
   10607 
   10608 /*
   10609  * Common code for handling a return instruction.
   10610  *
   10611  * This does not return.
   10612  */
   10613 common_returnFromMethod:
   10614 .LreturnNew:
   10615     mov     r0, #kInterpEntryReturn
   10616     mov     r9, #0
   10617     bl      common_periodicChecks
   10618 
   10619     SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
   10620     ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
   10621     ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
   10622     ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
   10623                                         @ r2<- method we're returning to
   10624     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
   10625     cmp     r2, #0                      @ is this a break frame?
   10626     ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
   10627     mov     r1, #0                      @ "want switch" = false
   10628     beq     common_gotoBail             @ break frame, bail out completely
   10629 
   10630     PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
   10631     str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
   10632     ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
   10633     str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
   10634 #if defined(WITH_JIT)
   10635     ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
   10636     mov     rPC, r9                     @ publish new rPC
   10637     str     r1, [rGLUE, #offGlue_methodClassDex]
   10638     str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
   10639     cmp     r10, #0                      @ caller is compiled code
   10640     blxne   r10
   10641     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10642     GOTO_OPCODE(ip)                     @ jump to next instruction
   10643 #else
   10644     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10645     mov     rPC, r9                     @ publish new rPC
   10646     str     r1, [rGLUE, #offGlue_methodClassDex]
   10647     GOTO_OPCODE(ip)                     @ jump to next instruction
   10648 #endif
   10649 
   10650     /*
   10651      * Return handling, calls through "glue code".
   10652      */
   10653      .if    0
   10654 .LreturnOld:
   10655     SAVE_PC_FP_TO_GLUE()                @ export state
   10656     mov     r0, rGLUE                   @ arg to function
   10657     bl      dvmMterp_returnFromMethod
   10658     b       common_resumeAfterGlueCall
   10659     .endif
   10660 
   10661 
   10662 /*
   10663  * Somebody has thrown an exception.  Handle it.
   10664  *
   10665  * If the exception processing code returns to us (instead of falling
   10666  * out of the interpreter), continue with whatever the next instruction
   10667  * now happens to be.
   10668  *
   10669  * This does not return.
   10670  */
   10671      .global dvmMterpCommonExceptionThrown
   10672 dvmMterpCommonExceptionThrown:
   10673 common_exceptionThrown:
   10674 .LexceptionNew:
   10675     mov     r0, #kInterpEntryThrow
   10676     mov     r9, #0
   10677     bl      common_periodicChecks
   10678 
   10679     ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
   10680     ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
   10681     mov     r1, r10                     @ r1<- self
   10682     mov     r0, r9                      @ r0<- exception
   10683     bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
   10684     mov     r3, #0                      @ r3<- NULL
   10685     str     r3, [r10, #offThread_exception] @ self->exception = NULL
   10686 
   10687     /* set up args and a local for "&fp" */
   10688     /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
   10689     str     rFP, [sp, #-4]!             @ *--sp = fp
   10690     mov     ip, sp                      @ ip<- &fp
   10691     mov     r3, #0                      @ r3<- false
   10692     str     ip, [sp, #-4]!              @ *--sp = &fp
   10693     ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
   10694     mov     r0, r10                     @ r0<- self
   10695     ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
   10696     mov     r2, r9                      @ r2<- exception
   10697     sub     r1, rPC, r1                 @ r1<- pc - method->insns
   10698     mov     r1, r1, asr #1              @ r1<- offset in code units
   10699 
   10700     /* call, r0 gets catchRelPc (a code-unit offset) */
   10701     bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
   10702 
   10703     /* fix earlier stack overflow if necessary; may trash rFP */
   10704     ldrb    r1, [r10, #offThread_stackOverflowed]
   10705     cmp     r1, #0                      @ did we overflow earlier?
   10706     beq     1f                          @ no, skip ahead
   10707     mov     rFP, r0                     @ save relPc result in rFP
   10708     mov     r0, r10                     @ r0<- self
   10709     mov     r1, r9                      @ r1<- exception
   10710     bl      dvmCleanupStackOverflow     @ call(self)
   10711     mov     r0, rFP                     @ restore result
   10712 1:
   10713 
   10714     /* update frame pointer and check result from dvmFindCatchBlock */
   10715     ldr     rFP, [sp, #4]               @ retrieve the updated rFP
   10716     cmp     r0, #0                      @ is catchRelPc < 0?
   10717     add     sp, sp, #8                  @ restore stack
   10718     bmi     .LnotCaughtLocally
   10719 
   10720     /* adjust locals to match self->curFrame and updated PC */
   10721     SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
   10722     ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
   10723     str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
   10724     ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
   10725     ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
   10726     ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
   10727     add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
   10728     str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
   10729 
   10730     /* release the tracked alloc on the exception */
   10731     mov     r0, r9                      @ r0<- exception
   10732     mov     r1, r10                     @ r1<- self
   10733     bl      dvmReleaseTrackedAlloc      @ release the exception
   10734 
   10735     /* restore the exception if the handler wants it */
   10736     FETCH_INST()                        @ load rINST from rPC
   10737     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10738     cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
   10739     streq   r9, [r10, #offThread_exception] @ yes, restore the exception
   10740     GOTO_OPCODE(ip)                     @ jump to next instruction
   10741 
   10742 .LnotCaughtLocally: @ r9=exception, r10=self
   10743     /* fix stack overflow if necessary */
   10744     ldrb    r1, [r10, #offThread_stackOverflowed]
   10745     cmp     r1, #0                      @ did we overflow earlier?
   10746     movne   r0, r10                     @ if yes: r0<- self
   10747     movne   r1, r9                      @ if yes: r1<- exception
   10748     blne    dvmCleanupStackOverflow     @ if yes: call(self)
   10749 
   10750     @ may want to show "not caught locally" debug messages here
   10751 #if DVM_SHOW_EXCEPTION >= 2
   10752     /* call __android_log_print(prio, tag, format, ...) */
   10753     /* "Exception %s from %s:%d not caught locally" */
   10754     @ dvmLineNumFromPC(method, pc - method->insns)
   10755     ldr     r0, [rGLUE, #offGlue_method]
   10756     ldr     r1, [r0, #offMethod_insns]
   10757     sub     r1, rPC, r1
   10758     asr     r1, r1, #1
   10759     bl      dvmLineNumFromPC
   10760     str     r0, [sp, #-4]!
   10761     @ dvmGetMethodSourceFile(method)
   10762     ldr     r0, [rGLUE, #offGlue_method]
   10763     bl      dvmGetMethodSourceFile
   10764     str     r0, [sp, #-4]!
   10765     @ exception->clazz->descriptor
   10766     ldr     r3, [r9, #offObject_clazz]
   10767     ldr     r3, [r3, #offClassObject_descriptor]
   10768     @
   10769     ldr     r2, strExceptionNotCaughtLocally
   10770     ldr     r1, strLogTag
   10771     mov     r0, #3                      @ LOG_DEBUG
   10772     bl      __android_log_print
   10773 #endif
   10774     str     r9, [r10, #offThread_exception] @ restore exception
   10775     mov     r0, r9                      @ r0<- exception
   10776     mov     r1, r10                     @ r1<- self
   10777     bl      dvmReleaseTrackedAlloc      @ release the exception
   10778     mov     r1, #0                      @ "want switch" = false
   10779     b       common_gotoBail             @ bail out
   10780 
   10781 
   10782     /*
   10783      * Exception handling, calls through "glue code".
   10784      */
   10785     .if     0
   10786 .LexceptionOld:
   10787     SAVE_PC_FP_TO_GLUE()                @ export state
   10788     mov     r0, rGLUE                   @ arg to function
   10789     bl      dvmMterp_exceptionThrown
   10790     b       common_resumeAfterGlueCall
   10791     .endif
   10792 
   10793 
   10794 /*
   10795  * After returning from a "glued" function, pull out the updated
   10796  * values and start executing at the next instruction.
   10797  */
   10798 common_resumeAfterGlueCall:
   10799     LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
   10800     FETCH_INST()                        @ load rINST from rPC
   10801     GET_INST_OPCODE(ip)                 @ extract opcode from rINST
   10802     GOTO_OPCODE(ip)                     @ jump to next instruction
   10803 
   10804 /*
   10805  * Invalid array index.
   10806  */
   10807 common_errArrayIndex:
   10808     EXPORT_PC()
   10809     ldr     r0, strArrayIndexException
   10810     mov     r1, #0
   10811     bl      dvmThrowException
   10812     b       common_exceptionThrown
   10813 
   10814 /*
   10815  * Invalid array value.
   10816  */
   10817 common_errArrayStore:
   10818     EXPORT_PC()
   10819     ldr     r0, strArrayStoreException
   10820     mov     r1, #0
   10821     bl      dvmThrowException
   10822     b       common_exceptionThrown
   10823 
   10824 /*
   10825  * Integer divide or mod by zero.
   10826  */
   10827 common_errDivideByZero:
   10828     EXPORT_PC()
   10829     ldr     r0, strArithmeticException
   10830     ldr     r1, strDivideByZero
   10831     bl      dvmThrowException
   10832     b       common_exceptionThrown
   10833 
   10834 /*
   10835  * Attempt to allocate an array with a negative size.
   10836  */
   10837 common_errNegativeArraySize:
   10838     EXPORT_PC()
   10839     ldr     r0, strNegativeArraySizeException
   10840     mov     r1, #0
   10841     bl      dvmThrowException
   10842     b       common_exceptionThrown
   10843 
   10844 /*
   10845  * Invocation of a non-existent method.
   10846  */
   10847 common_errNoSuchMethod:
   10848     EXPORT_PC()
   10849     ldr     r0, strNoSuchMethodError
   10850     mov     r1, #0
   10851     bl      dvmThrowException
   10852     b       common_exceptionThrown
   10853 
   10854 /*
   10855  * We encountered a null object when we weren't expecting one.  We
   10856  * export the PC, throw a NullPointerException, and goto the exception
   10857  * processing code.
   10858  */
   10859 common_errNullObject:
   10860     EXPORT_PC()
   10861     ldr     r0, strNullPointerException
   10862     mov     r1, #0
   10863     bl      dvmThrowException
   10864     b       common_exceptionThrown
   10865 
   10866 /*
   10867  * For debugging, cause an immediate fault.  The source address will
   10868  * be in lr (use a bl instruction to jump here).
   10869  */
   10870 common_abort:
   10871     ldr     pc, .LdeadFood
   10872 .LdeadFood:
   10873     .word   0xdeadf00d
   10874 
   10875 /*
   10876  * Spit out a "we were here", preserving all registers.  (The attempt
   10877  * to save ip won't work, but we need to save an even number of
   10878  * registers for EABI 64-bit stack alignment.)
   10879  */
   10880     .macro  SQUEAK num
   10881 common_squeak\num:
   10882     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10883     ldr     r0, strSqueak
   10884     mov     r1, #\num
   10885     bl      printf
   10886     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10887     bx      lr
   10888     .endm
   10889 
   10890     SQUEAK  0
   10891     SQUEAK  1
   10892     SQUEAK  2
   10893     SQUEAK  3
   10894     SQUEAK  4
   10895     SQUEAK  5
   10896 
   10897 /*
   10898  * Spit out the number in r0, preserving registers.
   10899  */
   10900 common_printNum:
   10901     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10902     mov     r1, r0
   10903     ldr     r0, strSqueak
   10904     bl      printf
   10905     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10906     bx      lr
   10907 
   10908 /*
   10909  * Print a newline, preserving registers.
   10910  */
   10911 common_printNewline:
   10912     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10913     ldr     r0, strNewline
   10914     bl      printf
   10915     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10916     bx      lr
   10917 
   10918     /*
   10919      * Print the 32-bit quantity in r0 as a hex value, preserving registers.
   10920      */
   10921 common_printHex:
   10922     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10923     mov     r1, r0
   10924     ldr     r0, strPrintHex
   10925     bl      printf
   10926     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10927     bx      lr
   10928 
   10929 /*
   10930  * Print the 64-bit quantity in r0-r1, preserving registers.
   10931  */
   10932 common_printLong:
   10933     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10934     mov     r3, r1
   10935     mov     r2, r0
   10936     ldr     r0, strPrintLong
   10937     bl      printf
   10938     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10939     bx      lr
   10940 
   10941 /*
   10942  * Print full method info.  Pass the Method* in r0.  Preserves regs.
   10943  */
   10944 common_printMethod:
   10945     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10946     bl      dvmMterpPrintMethod
   10947     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10948     bx      lr
   10949 
   10950 /*
   10951  * Call a C helper function that dumps regs and possibly some
   10952  * additional info.  Requires the C function to be compiled in.
   10953  */
   10954     .if     0
   10955 common_dumpRegs:
   10956     stmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10957     bl      dvmMterpDumpArmRegs
   10958     ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
   10959     bx      lr
   10960     .endif
   10961 
   10962 #if 0
   10963 /*
   10964  * Experiment on VFP mode.
   10965  *
   10966  * uint32_t setFPSCR(uint32_t val, uint32_t mask)
   10967  *
   10968  * Updates the bits specified by "mask", setting them to the values in "val".
   10969  */
   10970 setFPSCR:
   10971     and     r0, r0, r1                  @ make sure no stray bits are set
   10972     fmrx    r2, fpscr                   @ get VFP reg
   10973     mvn     r1, r1                      @ bit-invert mask
   10974     and     r2, r2, r1                  @ clear masked bits
   10975     orr     r2, r2, r0                  @ set specified bits
   10976     fmxr    fpscr, r2                   @ set VFP reg
   10977     mov     r0, r2                      @ return new value
   10978     bx      lr
   10979 
   10980     .align  2
   10981     .global dvmConfigureFP
   10982     .type   dvmConfigureFP, %function
   10983 dvmConfigureFP:
   10984     stmfd   sp!, {ip, lr}
   10985     /* 0x03000000 sets DN/FZ */
   10986     /* 0x00009f00 clears the six exception enable flags */
   10987     bl      common_squeak0
   10988     mov     r0, #0x03000000             @ r0<- 0x03000000
   10989     add     r1, r0, #0x9f00             @ r1<- 0x03009f00
   10990     bl      setFPSCR
   10991     ldmfd   sp!, {ip, pc}
   10992 #endif
   10993 
   10994 
   10995 /*
   10996  * String references, must be close to the code that uses them.
   10997  */
   10998     .align  2
   10999 strArithmeticException:
   11000     .word   .LstrArithmeticException
   11001 strArrayIndexException:
   11002     .word   .LstrArrayIndexException
   11003 strArrayStoreException:
   11004     .word   .LstrArrayStoreException
   11005 strDivideByZero:
   11006     .word   .LstrDivideByZero
   11007 strNegativeArraySizeException:
   11008     .word   .LstrNegativeArraySizeException
   11009 strNoSuchMethodError:
   11010     .word   .LstrNoSuchMethodError
   11011 strNullPointerException:
   11012     .word   .LstrNullPointerException
   11013 
   11014 strLogTag:
   11015     .word   .LstrLogTag
   11016 strExceptionNotCaughtLocally:
   11017     .word   .LstrExceptionNotCaughtLocally
   11018 
   11019 strNewline:
   11020     .word   .LstrNewline
   11021 strSqueak:
   11022     .word   .LstrSqueak
   11023 strPrintHex:
   11024     .word   .LstrPrintHex
   11025 strPrintLong:
   11026     .word   .LstrPrintLong
   11027 
   11028 /*
   11029  * Zero-terminated ASCII string data.
   11030  *
   11031  * On ARM we have two choices: do like gcc does, and LDR from a .word
   11032  * with the address, or use an ADR pseudo-op to get the address
   11033  * directly.  ADR saves 4 bytes and an indirection, but it's using a
   11034  * PC-relative addressing mode and hence has a limited range, which
   11035  * makes it not work well with mergeable string sections.
   11036  */
   11037     .section .rodata.str1.4,"aMS",%progbits,1
   11038 
   11039 .LstrBadEntryPoint:
   11040     .asciz  "Bad entry point %d\n"
   11041 .LstrArithmeticException:
   11042     .asciz  "Ljava/lang/ArithmeticException;"
   11043 .LstrArrayIndexException:
   11044     .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
   11045 .LstrArrayStoreException:
   11046     .asciz  "Ljava/lang/ArrayStoreException;"
   11047 .LstrClassCastException:
   11048     .asciz  "Ljava/lang/ClassCastException;"
   11049 .LstrDivideByZero:
   11050     .asciz  "divide by zero"
   11051 .LstrFilledNewArrayNotImpl:
   11052     .asciz  "filled-new-array only implemented for objects and 'int'"
   11053 .LstrInternalError:
   11054     .asciz  "Ljava/lang/InternalError;"
   11055 .LstrInstantiationError:
   11056     .asciz  "Ljava/lang/InstantiationError;"
   11057 .LstrNegativeArraySizeException:
   11058     .asciz  "Ljava/lang/NegativeArraySizeException;"
   11059 .LstrNoSuchMethodError:
   11060     .asciz  "Ljava/lang/NoSuchMethodError;"
   11061 .LstrNullPointerException:
   11062     .asciz  "Ljava/lang/NullPointerException;"
   11063 
   11064 .LstrLogTag:
   11065     .asciz  "mterp"
   11066 .LstrExceptionNotCaughtLocally:
   11067     .asciz  "Exception %s from %s:%d not caught locally\n"
   11068 
   11069 .LstrNewline:
   11070     .asciz  "\n"
   11071 .LstrSqueak:
   11072     .asciz  "<%d>"
   11073 .LstrPrintHex:
   11074     .asciz  "<0x%x>"
   11075 .LstrPrintLong:
   11076     .asciz  "<%lld>"
   11077 
   11078