InterpAsm-armv7-a-neon.S revision d3b0a4bf6b2e38e6e9e80e203ca753e941084103
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a-neon'.
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/*
29ARM EABI general notes:
30
31r0-r3 hold first 4 args to a method; they are not preserved across method calls
32r4-r8 are available for general use
33r9 is given special treatment in some situations, but not for us
34r10 (sl) seems to be generally available
35r11 (fp) is used by gcc (unless -fomit-frame-pointer is set)
36r12 (ip) is scratch -- not preserved across method calls
37r13 (sp) should be managed carefully in case a signal arrives
38r14 (lr) must be preserved
39r15 (pc) can be tinkered with directly
40
41r0 holds returns of <= 4 bytes
42r0-r1 hold returns of 8 bytes, low word in r0
43
44Callee must save/restore r4+ (except r12) if it modifies them.  If VFP
45is present, registers s16-s31 (a/k/a d8-d15, a/k/a q4-q7) must be preserved,
46s0-s15 (d0-d7, q0-a3) do not need to be.
47
48Stack is "full descending".  Only the arguments that don't fit in the first 4
49registers are placed on the stack.  "sp" points at the first stacked argument
50(i.e. the 5th arg).
51
52VFP: single-precision results in s0, double-precision results in d0.
53
54In the EABI, "sp" must be 64-bit aligned on entry to a function, and any
5564-bit quantities (long long, double) must be 64-bit aligned.
56*/
57
58/*
59Mterp and ARM notes:
60
61The 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
70Macros are provided for common operations.  Each macro MUST emit only
71one instruction to make instruction-counting easier.  They MUST NOT alter
72unspecified registers or condition codes.
73*/
74
75/* single-purpose registers, given names for clarity */
76#define rPC     r4
77#define rFP     r5
78#define rGLUE   r6
79#define rINST   r7
80#define rIBASE  r8
81
82/* save/restore the PC and/or FP from the glue struct */
83#define LOAD_PC_FROM_GLUE()     ldr     rPC, [rGLUE, #offGlue_pc]
84#define SAVE_PC_TO_GLUE()       str     rPC, [rGLUE, #offGlue_pc]
85#define LOAD_FP_FROM_GLUE()     ldr     rFP, [rGLUE, #offGlue_fp]
86#define SAVE_FP_TO_GLUE()       str     rFP, [rGLUE, #offGlue_fp]
87#define LOAD_PC_FP_FROM_GLUE()  ldmia   rGLUE, {rPC, rFP}
88#define SAVE_PC_FP_TO_GLUE()    stmia   rGLUE, {rPC, rFP}
89
90/*
91 * "export" the PC to the stack frame, f/b/o future exception objects.  Must
92 * be done *before* something calls dvmThrowException.
93 *
94 * In C this is "SAVEAREA_FROM_FP(fp)->xtra.currentPc = pc", i.e.
95 * fp - sizeof(StackSaveArea) + offsetof(SaveArea, xtra.currentPc)
96 *
97 * It's okay to do this more than once.
98 */
99#define EXPORT_PC() \
100    str     rPC, [rFP, #(-sizeofStackSaveArea + offStackSaveArea_currentPc)]
101
102/*
103 * Given a frame pointer, find the stack save area.
104 *
105 * In C this is "((StackSaveArea*)(_fp) -1)".
106 */
107#define SAVEAREA_FROM_FP(_reg, _fpreg) \
108    sub     _reg, _fpreg, #sizeofStackSaveArea
109
110/*
111 * Fetch the next instruction from rPC into rINST.  Does not advance rPC.
112 */
113#define FETCH_INST()            ldrh    rINST, [rPC]
114
115/*
116 * Fetch the next instruction from the specified offset.  Advances rPC
117 * to point to the next instruction.  "_count" is in 16-bit code units.
118 *
119 * Because of the limited size of immediate constants on ARM, this is only
120 * suitable for small forward movements (i.e. don't try to implement "goto"
121 * with this).
122 *
123 * This must come AFTER anything that can throw an exception, or the
124 * exception catch may miss.  (This also implies that it must come after
125 * EXPORT_PC().)
126 */
127#define FETCH_ADVANCE_INST(_count) ldrh    rINST, [rPC, #(_count*2)]!
128
129/*
130 * The operation performed here is similar to FETCH_ADVANCE_INST, except the
131 * src and dest registers are parameterized (not hard-wired to rPC and rINST).
132 */
133#define PREFETCH_ADVANCE_INST(_dreg, _sreg, _count) \
134        ldrh    _dreg, [_sreg, #(_count*2)]!
135
136/*
137 * Fetch the next instruction from an offset specified by _reg.  Updates
138 * rPC to point to the next instruction.  "_reg" must specify the distance
139 * in bytes, *not* 16-bit code units, and may be a signed value.
140 *
141 * We want to write "ldrh rINST, [rPC, _reg, lsl #2]!", but some of the
142 * bits that hold the shift distance are used for the half/byte/sign flags.
143 * In some cases we can pre-double _reg for free, so we require a byte offset
144 * here.
145 */
146#define FETCH_ADVANCE_INST_RB(_reg) ldrh    rINST, [rPC, _reg]!
147
148/*
149 * Fetch a half-word code unit from an offset past the current PC.  The
150 * "_count" value is in 16-bit code units.  Does not advance rPC.
151 *
152 * The "_S" variant works the same but treats the value as signed.
153 */
154#define FETCH(_reg, _count)     ldrh    _reg, [rPC, #(_count*2)]
155#define FETCH_S(_reg, _count)   ldrsh   _reg, [rPC, #(_count*2)]
156
157/*
158 * Fetch one byte from an offset past the current PC.  Pass in the same
159 * "_count" as you would for FETCH, and an additional 0/1 indicating which
160 * byte of the halfword you want (lo/hi).
161 */
162#define FETCH_B(_reg, _count, _byte) ldrb     _reg, [rPC, #(_count*2+_byte)]
163
164/*
165 * Put the instruction's opcode field into the specified register.
166 */
167#define GET_INST_OPCODE(_reg)   and     _reg, rINST, #255
168
169/*
170 * Put the prefetched instruction's opcode field into the specified register.
171 */
172#define GET_PREFETCHED_OPCODE(_oreg, _ireg)   and     _oreg, _ireg, #255
173
174/*
175 * Begin executing the opcode in _reg.  Because this only jumps within the
176 * interpreter, we don't have to worry about pre-ARMv5 THUMB interwork.
177 */
178#define GOTO_OPCODE(_reg)       add     pc, rIBASE, _reg, lsl #6
179#define GOTO_OPCODE_IFEQ(_reg)  addeq   pc, rIBASE, _reg, lsl #6
180#define GOTO_OPCODE_IFNE(_reg)  addne   pc, rIBASE, _reg, lsl #6
181
182/*
183 * Get/set the 32-bit value from a Dalvik register.
184 */
185#define GET_VREG(_reg, _vreg)   ldr     _reg, [rFP, _vreg, lsl #2]
186#define SET_VREG(_reg, _vreg)   str     _reg, [rFP, _vreg, lsl #2]
187
188#if defined(WITH_JIT)
189#define GET_JIT_PROF_TABLE(_reg)    ldr     _reg,[rGLUE,#offGlue_pJitProfTable]
190#define GET_JIT_THRESHOLD(_reg)     ldr     _reg,[rGLUE,#offGlue_jitThreshold]
191#endif
192
193/*
194 * Convert a virtual register index into an address.
195 */
196#define VREG_INDEX_TO_ADDR(_reg, _vreg) \
197        add     _reg, rFP, _vreg, lsl #2
198
199/*
200 * This is a #include, not a %include, because we want the C pre-processor
201 * to expand the macros into assembler assignment statements.
202 */
203#include "../common/asm-constants.h"
204
205#if defined(WITH_JIT)
206#include "../common/jit-config.h"
207#endif
208
209/* File: armv7-a/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216/*
217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
218 * one-way branch.
219 *
220 * May modify IP.  Does not modify LR.
221 */
222.macro  LDR_PC source
223    ldr     pc, \source
224.endm
225
226/*
227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
228 * Jump to subroutine.
229 *
230 * May modify IP and LR.
231 */
232.macro  LDR_PC_LR source
233    mov     lr, pc
234    ldr     pc, \source
235.endm
236
237/*
238 * Macro for "LDMFD SP!, {...regs...,PC}".
239 *
240 * May modify IP and LR.
241 */
242.macro  LDMFD_PC regs
243    ldmfd   sp!, {\regs,pc}
244.endm
245
246#if !defined(ANDROID_SMP)
247# error "Must define ANDROID_SMP"
248#endif
249
250/*
251 * Macro for data memory barrier.
252 */
253.macro  SMP_DMB
254#if ANDROID_SMP != 0
255    dmb
256#else
257    /* not SMP */
258#endif
259.endm
260
261/*
262 * Macro for data memory barrier (store/store variant).
263 */
264.macro  SMP_DMB_ST
265#if ANDROID_SMP != 0
266    dmb                                 @ TODO: want "dmb st" here
267#else
268    /* not SMP */
269#endif
270.endm
271
272/* File: armv5te/entry.S */
273/*
274 * Copyright (C) 2008 The Android Open Source Project
275 *
276 * Licensed under the Apache License, Version 2.0 (the "License");
277 * you may not use this file except in compliance with the License.
278 * You may obtain a copy of the License at
279 *
280 *      http://www.apache.org/licenses/LICENSE-2.0
281 *
282 * Unless required by applicable law or agreed to in writing, software
283 * distributed under the License is distributed on an "AS IS" BASIS,
284 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
285 * See the License for the specific language governing permissions and
286 * limitations under the License.
287 */
288/*
289 * Interpreter entry point.
290 */
291
292/*
293 * We don't have formal stack frames, so gdb scans upward in the code
294 * to find the start of the function (a label with the %function type),
295 * and then looks at the next few instructions to figure out what
296 * got pushed onto the stack.  From this it figures out how to restore
297 * the registers, including PC, for the previous stack frame.  If gdb
298 * sees a non-function label, it stops scanning, so either we need to
299 * have nothing but assembler-local labels between the entry point and
300 * the break, or we need to fake it out.
301 *
302 * When this is defined, we add some stuff to make gdb less confused.
303 */
304#define ASSIST_DEBUGGER 1
305
306    .text
307    .align  2
308    .global dvmMterpStdRun
309    .type   dvmMterpStdRun, %function
310
311/*
312 * On entry:
313 *  r0  MterpGlue* glue
314 *
315 * This function returns a boolean "changeInterp" value.  The return comes
316 * via a call to dvmMterpStdBail().
317 */
318dvmMterpStdRun:
319#define MTERP_ENTRY1 \
320    .save {r4-r10,fp,lr}; \
321    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
322#define MTERP_ENTRY2 \
323    .pad    #4; \
324    sub     sp, sp, #4                  @ align 64
325
326    .fnstart
327    MTERP_ENTRY1
328    MTERP_ENTRY2
329
330    /* save stack pointer, add magic word for debuggerd */
331    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
332
333    /* set up "named" registers, figure out entry point */
334    mov     rGLUE, r0                   @ set rGLUE
335    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
336    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
337    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
338    cmp     r1, #kInterpEntryInstr      @ usual case?
339    bne     .Lnot_instr                 @ no, handle it
340
341#if defined(WITH_JIT)
342.LentryInstr:
343    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
344    /* Entry is always a possible trace start */
345    GET_JIT_PROF_TABLE(r0)
346    FETCH_INST()
347    mov     r1, #0                      @ prepare the value for the new state
348    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
349    cmp     r0,#0                       @ is profiling disabled?
350#if !defined(WITH_SELF_VERIFICATION)
351    bne     common_updateProfile        @ profiling is enabled
352#else
353    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
354    beq     1f                          @ profiling is disabled
355    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
356    cmp     r3, #kSVSTraceSelect        @ hot trace following?
357    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
358    beq     common_selectTrace          @ go build the trace
359    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
360    beq     1f                          @ intrepret the next instruction
361    b       common_updateProfile        @ collect profiles
362#endif
3631:
364    GET_INST_OPCODE(ip)
365    GOTO_OPCODE(ip)
366#else
367    /* start executing the instruction at rPC */
368    FETCH_INST()                        @ load rINST from rPC
369    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
370    GOTO_OPCODE(ip)                     @ jump to next instruction
371#endif
372
373.Lnot_instr:
374    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
375    beq     common_returnFromMethod
376
377.Lnot_return:
378    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
379    beq     common_exceptionThrown
380
381#if defined(WITH_JIT)
382.Lnot_throw:
383    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
384    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
385    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
386    bne     .Lbad_arg
387    cmp     rPC,r2
388    bne     .LentryInstr                @ must have branched, don't resume
389#if defined(WITH_SELF_VERIFICATION)
390    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
391    b       jitSVShadowRunStart         @ re-enter the translation after the
392                                        @ single-stepped instruction
393    @noreturn
394#endif
395    mov     r1, #kInterpEntryInstr
396    str     r1, [rGLUE, #offGlue_entryPoint]
397    bx      r10                         @ re-enter the translation
398#endif
399
400.Lbad_arg:
401    ldr     r0, strBadEntryPoint
402    @ r1 holds value of entryPoint
403    bl      printf
404    bl      dvmAbort
405    .fnend
406
407
408    .global dvmMterpStdBail
409    .type   dvmMterpStdBail, %function
410
411/*
412 * Restore the stack pointer and PC from the save point established on entry.
413 * This is essentially the same as a longjmp, but should be cheaper.  The
414 * last instruction causes us to return to whoever called dvmMterpStdRun.
415 *
416 * We pushed some registers on the stack in dvmMterpStdRun, then saved
417 * SP and LR.  Here we restore SP, restore the registers, and then restore
418 * LR to PC.
419 *
420 * On entry:
421 *  r0  MterpGlue* glue
422 *  r1  bool changeInterp
423 */
424dvmMterpStdBail:
425    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
426    mov     r0, r1                          @ return the changeInterp value
427    add     sp, sp, #4                      @ un-align 64
428    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
429
430
431/*
432 * String references.
433 */
434strBadEntryPoint:
435    .word   .LstrBadEntryPoint
436
437
438    .global dvmAsmInstructionStart
439    .type   dvmAsmInstructionStart, %function
440dvmAsmInstructionStart = .L_OP_NOP
441    .text
442
443/* ------------------------------ */
444    .balign 64
445.L_OP_NOP: /* 0x00 */
446/* File: armv5te/OP_NOP.S */
447    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
448    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
449    GOTO_OPCODE(ip)                     @ execute it
450
451#ifdef ASSIST_DEBUGGER
452    /* insert fake function header to help gdb find the stack frame */
453    .type   dalvik_inst, %function
454dalvik_inst:
455    .fnstart
456    MTERP_ENTRY1
457    MTERP_ENTRY2
458    .fnend
459#endif
460
461/* ------------------------------ */
462    .balign 64
463.L_OP_MOVE: /* 0x01 */
464/* File: armv6t2/OP_MOVE.S */
465    /* for move, move-object, long-to-int */
466    /* op vA, vB */
467    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
468    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
469    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
470    GET_VREG(r2, r1)                    @ r2<- fp[B]
471    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
472    SET_VREG(r2, r0)                    @ fp[A]<- r2
473    GOTO_OPCODE(ip)                     @ execute next instruction
474
475/* ------------------------------ */
476    .balign 64
477.L_OP_MOVE_FROM16: /* 0x02 */
478/* File: armv5te/OP_MOVE_FROM16.S */
479    /* for: move/from16, move-object/from16 */
480    /* op vAA, vBBBB */
481    FETCH(r1, 1)                        @ r1<- BBBB
482    mov     r0, rINST, lsr #8           @ r0<- AA
483    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
484    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
486    SET_VREG(r2, r0)                    @ fp[AA]<- r2
487    GOTO_OPCODE(ip)                     @ jump to next instruction
488
489/* ------------------------------ */
490    .balign 64
491.L_OP_MOVE_16: /* 0x03 */
492/* File: armv5te/OP_MOVE_16.S */
493    /* for: move/16, move-object/16 */
494    /* op vAAAA, vBBBB */
495    FETCH(r1, 2)                        @ r1<- BBBB
496    FETCH(r0, 1)                        @ r0<- AAAA
497    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
498    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
499    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
500    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
501    GOTO_OPCODE(ip)                     @ jump to next instruction
502
503/* ------------------------------ */
504    .balign 64
505.L_OP_MOVE_WIDE: /* 0x04 */
506/* File: armv6t2/OP_MOVE_WIDE.S */
507    /* move-wide vA, vB */
508    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
509    mov     r3, rINST, lsr #12          @ r3<- B
510    ubfx    r2, rINST, #8, #4           @ r2<- A
511    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
512    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
513    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
514    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
515    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
516    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
517    GOTO_OPCODE(ip)                     @ jump to next instruction
518
519/* ------------------------------ */
520    .balign 64
521.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
522/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
523    /* move-wide/from16 vAA, vBBBB */
524    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
525    FETCH(r3, 1)                        @ r3<- BBBB
526    mov     r2, rINST, lsr #8           @ r2<- AA
527    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
528    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
529    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
530    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
532    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
533    GOTO_OPCODE(ip)                     @ jump to next instruction
534
535/* ------------------------------ */
536    .balign 64
537.L_OP_MOVE_WIDE_16: /* 0x06 */
538/* File: armv5te/OP_MOVE_WIDE_16.S */
539    /* move-wide/16 vAAAA, vBBBB */
540    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
541    FETCH(r3, 2)                        @ r3<- BBBB
542    FETCH(r2, 1)                        @ r2<- AAAA
543    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
544    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
545    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
546    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
547    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
548    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
549    GOTO_OPCODE(ip)                     @ jump to next instruction
550
551/* ------------------------------ */
552    .balign 64
553.L_OP_MOVE_OBJECT: /* 0x07 */
554/* File: armv5te/OP_MOVE_OBJECT.S */
555/* File: armv5te/OP_MOVE.S */
556    /* for move, move-object, long-to-int */
557    /* op vA, vB */
558    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
559    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
560    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
561    GET_VREG(r2, r1)                    @ r2<- fp[B]
562    and     r0, r0, #15
563    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
564    SET_VREG(r2, r0)                    @ fp[A]<- r2
565    GOTO_OPCODE(ip)                     @ execute next instruction
566
567
568/* ------------------------------ */
569    .balign 64
570.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
571/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
572/* File: armv5te/OP_MOVE_FROM16.S */
573    /* for: move/from16, move-object/from16 */
574    /* op vAA, vBBBB */
575    FETCH(r1, 1)                        @ r1<- BBBB
576    mov     r0, rINST, lsr #8           @ r0<- AA
577    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
578    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
580    SET_VREG(r2, r0)                    @ fp[AA]<- r2
581    GOTO_OPCODE(ip)                     @ jump to next instruction
582
583
584/* ------------------------------ */
585    .balign 64
586.L_OP_MOVE_OBJECT_16: /* 0x09 */
587/* File: armv5te/OP_MOVE_OBJECT_16.S */
588/* File: armv5te/OP_MOVE_16.S */
589    /* for: move/16, move-object/16 */
590    /* op vAAAA, vBBBB */
591    FETCH(r1, 2)                        @ r1<- BBBB
592    FETCH(r0, 1)                        @ r0<- AAAA
593    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
594    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
595    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
596    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
597    GOTO_OPCODE(ip)                     @ jump to next instruction
598
599
600/* ------------------------------ */
601    .balign 64
602.L_OP_MOVE_RESULT: /* 0x0a */
603/* File: armv5te/OP_MOVE_RESULT.S */
604    /* for: move-result, move-result-object */
605    /* op vAA */
606    mov     r2, rINST, lsr #8           @ r2<- AA
607    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
608    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
609    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
610    SET_VREG(r0, r2)                    @ fp[AA]<- r0
611    GOTO_OPCODE(ip)                     @ jump to next instruction
612
613/* ------------------------------ */
614    .balign 64
615.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
616/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
617    /* move-result-wide vAA */
618    mov     r2, rINST, lsr #8           @ r2<- AA
619    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
620    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
621    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
622    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
623    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
624    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
625    GOTO_OPCODE(ip)                     @ jump to next instruction
626
627/* ------------------------------ */
628    .balign 64
629.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
630/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
631/* File: armv5te/OP_MOVE_RESULT.S */
632    /* for: move-result, move-result-object */
633    /* op vAA */
634    mov     r2, rINST, lsr #8           @ r2<- AA
635    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
636    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
637    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
638    SET_VREG(r0, r2)                    @ fp[AA]<- r0
639    GOTO_OPCODE(ip)                     @ jump to next instruction
640
641
642/* ------------------------------ */
643    .balign 64
644.L_OP_MOVE_EXCEPTION: /* 0x0d */
645/* File: armv5te/OP_MOVE_EXCEPTION.S */
646    /* move-exception vAA */
647    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
648    mov     r2, rINST, lsr #8           @ r2<- AA
649    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
650    mov     r1, #0                      @ r1<- 0
651    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
652    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
654    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
655    GOTO_OPCODE(ip)                     @ jump to next instruction
656
657/* ------------------------------ */
658    .balign 64
659.L_OP_RETURN_VOID: /* 0x0e */
660/* File: armv5te/OP_RETURN_VOID.S */
661    b       common_returnFromMethod
662
663/* ------------------------------ */
664    .balign 64
665.L_OP_RETURN: /* 0x0f */
666/* File: armv5te/OP_RETURN.S */
667    /*
668     * Return a 32-bit value.  Copies the return value into the "glue"
669     * structure, then jumps to the return handler.
670     *
671     * for: return, return-object
672     */
673    /* op vAA */
674    mov     r2, rINST, lsr #8           @ r2<- AA
675    GET_VREG(r0, r2)                    @ r0<- vAA
676    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
677    b       common_returnFromMethod
678
679/* ------------------------------ */
680    .balign 64
681.L_OP_RETURN_WIDE: /* 0x10 */
682/* File: armv5te/OP_RETURN_WIDE.S */
683    /*
684     * Return a 64-bit value.  Copies the return value into the "glue"
685     * structure, then jumps to the return handler.
686     */
687    /* return-wide vAA */
688    mov     r2, rINST, lsr #8           @ r2<- AA
689    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
690    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
691    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
692    stmia   r3, {r0-r1}                 @ retval<- r0/r1
693    b       common_returnFromMethod
694
695/* ------------------------------ */
696    .balign 64
697.L_OP_RETURN_OBJECT: /* 0x11 */
698/* File: armv5te/OP_RETURN_OBJECT.S */
699/* File: armv5te/OP_RETURN.S */
700    /*
701     * Return a 32-bit value.  Copies the return value into the "glue"
702     * structure, then jumps to the return handler.
703     *
704     * for: return, return-object
705     */
706    /* op vAA */
707    mov     r2, rINST, lsr #8           @ r2<- AA
708    GET_VREG(r0, r2)                    @ r0<- vAA
709    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
710    b       common_returnFromMethod
711
712
713/* ------------------------------ */
714    .balign 64
715.L_OP_CONST_4: /* 0x12 */
716/* File: armv6t2/OP_CONST_4.S */
717    /* const/4 vA, #+B */
718    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
719    ubfx    r0, rINST, #8, #4           @ r0<- A
720    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
721    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
722    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
723    SET_VREG(r1, r0)                    @ fp[A]<- r1
724    GOTO_OPCODE(ip)                     @ execute next instruction
725
726/* ------------------------------ */
727    .balign 64
728.L_OP_CONST_16: /* 0x13 */
729/* File: armv5te/OP_CONST_16.S */
730    /* const/16 vAA, #+BBBB */
731    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
732    mov     r3, rINST, lsr #8           @ r3<- AA
733    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
734    SET_VREG(r0, r3)                    @ vAA<- r0
735    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
736    GOTO_OPCODE(ip)                     @ jump to next instruction
737
738/* ------------------------------ */
739    .balign 64
740.L_OP_CONST: /* 0x14 */
741/* File: armv5te/OP_CONST.S */
742    /* const vAA, #+BBBBbbbb */
743    mov     r3, rINST, lsr #8           @ r3<- AA
744    FETCH(r0, 1)                        @ r0<- bbbb (low)
745    FETCH(r1, 2)                        @ r1<- BBBB (high)
746    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
747    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
748    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
749    SET_VREG(r0, r3)                    @ vAA<- r0
750    GOTO_OPCODE(ip)                     @ jump to next instruction
751
752/* ------------------------------ */
753    .balign 64
754.L_OP_CONST_HIGH16: /* 0x15 */
755/* File: armv5te/OP_CONST_HIGH16.S */
756    /* const/high16 vAA, #+BBBB0000 */
757    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
758    mov     r3, rINST, lsr #8           @ r3<- AA
759    mov     r0, r0, lsl #16             @ r0<- BBBB0000
760    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
761    SET_VREG(r0, r3)                    @ vAA<- r0
762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
763    GOTO_OPCODE(ip)                     @ jump to next instruction
764
765/* ------------------------------ */
766    .balign 64
767.L_OP_CONST_WIDE_16: /* 0x16 */
768/* File: armv5te/OP_CONST_WIDE_16.S */
769    /* const-wide/16 vAA, #+BBBB */
770    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
771    mov     r3, rINST, lsr #8           @ r3<- AA
772    mov     r1, r0, asr #31             @ r1<- ssssssss
773    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
774    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
776    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
777    GOTO_OPCODE(ip)                     @ jump to next instruction
778
779/* ------------------------------ */
780    .balign 64
781.L_OP_CONST_WIDE_32: /* 0x17 */
782/* File: armv5te/OP_CONST_WIDE_32.S */
783    /* const-wide/32 vAA, #+BBBBbbbb */
784    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
785    mov     r3, rINST, lsr #8           @ r3<- AA
786    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
787    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
788    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
789    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
790    mov     r1, r0, asr #31             @ r1<- ssssssss
791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
792    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
793    GOTO_OPCODE(ip)                     @ jump to next instruction
794
795/* ------------------------------ */
796    .balign 64
797.L_OP_CONST_WIDE: /* 0x18 */
798/* File: armv5te/OP_CONST_WIDE.S */
799    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
800    FETCH(r0, 1)                        @ r0<- bbbb (low)
801    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
802    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
803    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
804    FETCH(r3, 4)                        @ r3<- HHHH (high)
805    mov     r9, rINST, lsr #8           @ r9<- AA
806    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
807    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
808    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
809    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
810    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
811    GOTO_OPCODE(ip)                     @ jump to next instruction
812
813/* ------------------------------ */
814    .balign 64
815.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
816/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
817    /* const-wide/high16 vAA, #+BBBB000000000000 */
818    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
819    mov     r3, rINST, lsr #8           @ r3<- AA
820    mov     r0, #0                      @ r0<- 00000000
821    mov     r1, r1, lsl #16             @ r1<- BBBB0000
822    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
823    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
825    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
826    GOTO_OPCODE(ip)                     @ jump to next instruction
827
828/* ------------------------------ */
829    .balign 64
830.L_OP_CONST_STRING: /* 0x1a */
831/* File: armv5te/OP_CONST_STRING.S */
832    /* const/string vAA, String@BBBB */
833    FETCH(r1, 1)                        @ r1<- BBBB
834    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
835    mov     r9, rINST, lsr #8           @ r9<- AA
836    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
837    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
838    cmp     r0, #0                      @ not yet resolved?
839    beq     .LOP_CONST_STRING_resolve
840    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
842    SET_VREG(r0, r9)                    @ vAA<- r0
843    GOTO_OPCODE(ip)                     @ jump to next instruction
844
845/* ------------------------------ */
846    .balign 64
847.L_OP_CONST_STRING_JUMBO: /* 0x1b */
848/* File: armv5te/OP_CONST_STRING_JUMBO.S */
849    /* const/string vAA, String@BBBBBBBB */
850    FETCH(r0, 1)                        @ r0<- bbbb (low)
851    FETCH(r1, 2)                        @ r1<- BBBB (high)
852    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
853    mov     r9, rINST, lsr #8           @ r9<- AA
854    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
855    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
856    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
857    cmp     r0, #0
858    beq     .LOP_CONST_STRING_JUMBO_resolve
859    FETCH_ADVANCE_INST(3)               @ 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_CONST_CLASS: /* 0x1c */
867/* File: armv5te/OP_CONST_CLASS.S */
868    /* const/class vAA, Class@BBBB */
869    FETCH(r1, 1)                        @ r1<- BBBB
870    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
871    mov     r9, rINST, lsr #8           @ r9<- AA
872    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
873    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
874    cmp     r0, #0                      @ not yet resolved?
875    beq     .LOP_CONST_CLASS_resolve
876    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
878    SET_VREG(r0, r9)                    @ vAA<- r0
879    GOTO_OPCODE(ip)                     @ jump to next instruction
880
881/* ------------------------------ */
882    .balign 64
883.L_OP_MONITOR_ENTER: /* 0x1d */
884/* File: armv5te/OP_MONITOR_ENTER.S */
885    /*
886     * Synchronize on an object.
887     */
888    /* monitor-enter vAA */
889    mov     r2, rINST, lsr #8           @ r2<- AA
890    GET_VREG(r1, r2)                    @ r1<- vAA (object)
891    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
892    cmp     r1, #0                      @ null object?
893    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
894    beq     common_errNullObject        @ null object, throw an exception
895    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
896    bl      dvmLockObject               @ call(self, obj)
897#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
898    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
899    ldr     r1, [r0, #offThread_exception] @ check for exception
900    cmp     r1, #0
901    bne     common_exceptionThrown      @ exception raised, bail out
902#endif
903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
904    GOTO_OPCODE(ip)                     @ jump to next instruction
905
906/* ------------------------------ */
907    .balign 64
908.L_OP_MONITOR_EXIT: /* 0x1e */
909/* File: armv5te/OP_MONITOR_EXIT.S */
910    /*
911     * Unlock an object.
912     *
913     * Exceptions that occur when unlocking a monitor need to appear as
914     * if they happened at the following instruction.  See the Dalvik
915     * instruction spec.
916     */
917    /* monitor-exit vAA */
918    mov     r2, rINST, lsr #8           @ r2<- AA
919    EXPORT_PC()                         @ before fetch: export the PC
920    GET_VREG(r1, r2)                    @ r1<- vAA (object)
921    cmp     r1, #0                      @ null object?
922    beq     1f                          @ yes
923    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
924    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
925    cmp     r0, #0                      @ failed?
926    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
927    beq     common_exceptionThrown      @ yes, exception is pending
928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
929    GOTO_OPCODE(ip)                     @ jump to next instruction
9301:
931    FETCH_ADVANCE_INST(1)               @ advance before throw
932    b      common_errNullObject
933
934/* ------------------------------ */
935    .balign 64
936.L_OP_CHECK_CAST: /* 0x1f */
937/* File: armv5te/OP_CHECK_CAST.S */
938    /*
939     * Check to see if a cast from one class to another is allowed.
940     */
941    /* check-cast vAA, class@BBBB */
942    mov     r3, rINST, lsr #8           @ r3<- AA
943    FETCH(r2, 1)                        @ r2<- BBBB
944    GET_VREG(r9, r3)                    @ r9<- object
945    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
946    cmp     r9, #0                      @ is object null?
947    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
948    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
949    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
950    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
951    cmp     r1, #0                      @ have we resolved this before?
952    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
953.LOP_CHECK_CAST_resolved:
954    cmp     r0, r1                      @ same class (trivial success)?
955    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
956.LOP_CHECK_CAST_okay:
957    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
958    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
959    GOTO_OPCODE(ip)                     @ jump to next instruction
960
961/* ------------------------------ */
962    .balign 64
963.L_OP_INSTANCE_OF: /* 0x20 */
964/* File: armv5te/OP_INSTANCE_OF.S */
965    /*
966     * Check to see if an object reference is an instance of a class.
967     *
968     * Most common situation is a non-null object, being compared against
969     * an already-resolved class.
970     */
971    /* instance-of vA, vB, class@CCCC */
972    mov     r3, rINST, lsr #12          @ r3<- B
973    mov     r9, rINST, lsr #8           @ r9<- A+
974    GET_VREG(r0, r3)                    @ r0<- vB (object)
975    and     r9, r9, #15                 @ r9<- A
976    cmp     r0, #0                      @ is object null?
977    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
978    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
979    FETCH(r3, 1)                        @ r3<- CCCC
980    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
981    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
982    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
983    cmp     r1, #0                      @ have we resolved this before?
984    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
985.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
986    cmp     r0, r1                      @ same class (trivial success)?
987    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
988    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
989
990/* ------------------------------ */
991    .balign 64
992.L_OP_ARRAY_LENGTH: /* 0x21 */
993/* File: armv6t2/OP_ARRAY_LENGTH.S */
994    /*
995     * Return the length of an array.
996     */
997    mov     r1, rINST, lsr #12          @ r1<- B
998    ubfx    r2, rINST, #8, #4           @ r2<- A
999    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
1000    cmp     r0, #0                      @ is object null?
1001    beq     common_errNullObject        @ yup, fail
1002    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
1003    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
1004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1005    SET_VREG(r3, r2)                    @ vB<- length
1006    GOTO_OPCODE(ip)                     @ jump to next instruction
1007
1008/* ------------------------------ */
1009    .balign 64
1010.L_OP_NEW_INSTANCE: /* 0x22 */
1011/* File: armv5te/OP_NEW_INSTANCE.S */
1012    /*
1013     * Create a new instance of a class.
1014     */
1015    /* new-instance vAA, class@BBBB */
1016    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1017    FETCH(r1, 1)                        @ r1<- BBBB
1018    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1019    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1020    EXPORT_PC()                         @ req'd for init, resolve, alloc
1021    cmp     r0, #0                      @ already resolved?
1022    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1023.LOP_NEW_INSTANCE_resolved:   @ r0=class
1024    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1025    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1026    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1027.LOP_NEW_INSTANCE_initialized: @ r0=class
1028    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1029    bl      dvmAllocObject              @ r0<- new object
1030    b       .LOP_NEW_INSTANCE_finish          @ continue
1031
1032/* ------------------------------ */
1033    .balign 64
1034.L_OP_NEW_ARRAY: /* 0x23 */
1035/* File: armv5te/OP_NEW_ARRAY.S */
1036    /*
1037     * Allocate an array of objects, specified with the array class
1038     * and a count.
1039     *
1040     * The verifier guarantees that this is an array class, so we don't
1041     * check for it here.
1042     */
1043    /* new-array vA, vB, class@CCCC */
1044    mov     r0, rINST, lsr #12          @ r0<- B
1045    FETCH(r2, 1)                        @ r2<- CCCC
1046    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1047    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1048    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1049    cmp     r1, #0                      @ check length
1050    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1051    bmi     common_errNegativeArraySize @ negative length, bail
1052    cmp     r0, #0                      @ already resolved?
1053    EXPORT_PC()                         @ req'd for resolve, alloc
1054    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1055    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1056
1057/* ------------------------------ */
1058    .balign 64
1059.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1060/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1061    /*
1062     * Create a new array with elements filled from registers.
1063     *
1064     * for: filled-new-array, filled-new-array/range
1065     */
1066    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1067    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1068    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1069    FETCH(r1, 1)                        @ r1<- BBBB
1070    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1071    EXPORT_PC()                         @ need for resolve and alloc
1072    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1073    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1074    cmp     r0, #0                      @ already resolved?
1075    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10768:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1077    mov     r2, #0                      @ r2<- false
1078    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1079    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1080    cmp     r0, #0                      @ got null?
1081    beq     common_exceptionThrown      @ yes, handle exception
1082    b       .LOP_FILLED_NEW_ARRAY_continue
1083
1084/* ------------------------------ */
1085    .balign 64
1086.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1087/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1088/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1089    /*
1090     * Create a new array with elements filled from registers.
1091     *
1092     * for: filled-new-array, filled-new-array/range
1093     */
1094    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1095    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1096    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1097    FETCH(r1, 1)                        @ r1<- BBBB
1098    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1099    EXPORT_PC()                         @ need for resolve and alloc
1100    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1101    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1102    cmp     r0, #0                      @ already resolved?
1103    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
11048:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1105    mov     r2, #0                      @ r2<- false
1106    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1107    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1108    cmp     r0, #0                      @ got null?
1109    beq     common_exceptionThrown      @ yes, handle exception
1110    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1111
1112
1113/* ------------------------------ */
1114    .balign 64
1115.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1116/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1117    /* fill-array-data vAA, +BBBBBBBB */
1118    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1119    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1120    mov     r3, rINST, lsr #8           @ r3<- AA
1121    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1122    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1123    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1124    EXPORT_PC();
1125    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1126    cmp     r0, #0                      @ 0 means an exception is thrown
1127    beq     common_exceptionThrown      @ has exception
1128    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1130    GOTO_OPCODE(ip)                     @ jump to next instruction
1131
1132/* ------------------------------ */
1133    .balign 64
1134.L_OP_THROW: /* 0x27 */
1135/* File: armv5te/OP_THROW.S */
1136    /*
1137     * Throw an exception object in the current thread.
1138     */
1139    /* throw vAA */
1140    mov     r2, rINST, lsr #8           @ r2<- AA
1141    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1142    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1143    EXPORT_PC()                         @ exception handler can throw
1144    cmp     r1, #0                      @ null object?
1145    beq     common_errNullObject        @ yes, throw an NPE instead
1146    @ bypass dvmSetException, just store it
1147    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1148    b       common_exceptionThrown
1149
1150/* ------------------------------ */
1151    .balign 64
1152.L_OP_GOTO: /* 0x28 */
1153/* File: armv5te/OP_GOTO.S */
1154    /*
1155     * Unconditional branch, 8-bit offset.
1156     *
1157     * The branch distance is a signed code-unit offset, which we need to
1158     * double to get a byte offset.
1159     */
1160    /* goto +AA */
1161    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1162    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1163    mov     r9, r9, lsl #1              @ r9<- byte offset
1164    bmi     common_backwardBranch       @ backward branch, do periodic checks
1165#if defined(WITH_JIT)
1166    GET_JIT_PROF_TABLE(r0)
1167    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1168    cmp     r0,#0
1169    bne     common_updateProfile
1170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1171    GOTO_OPCODE(ip)                     @ jump to next instruction
1172#else
1173    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1175    GOTO_OPCODE(ip)                     @ jump to next instruction
1176#endif
1177
1178/* ------------------------------ */
1179    .balign 64
1180.L_OP_GOTO_16: /* 0x29 */
1181/* File: armv5te/OP_GOTO_16.S */
1182    /*
1183     * Unconditional branch, 16-bit offset.
1184     *
1185     * The branch distance is a signed code-unit offset, which we need to
1186     * double to get a byte offset.
1187     */
1188    /* goto/16 +AAAA */
1189    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1190    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1191    bmi     common_backwardBranch       @ backward branch, do periodic checks
1192#if defined(WITH_JIT)
1193    GET_JIT_PROF_TABLE(r0)
1194    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1195    cmp     r0,#0
1196    bne     common_updateProfile
1197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1198    GOTO_OPCODE(ip)                     @ jump to next instruction
1199#else
1200    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1201    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1202    GOTO_OPCODE(ip)                     @ jump to next instruction
1203#endif
1204
1205/* ------------------------------ */
1206    .balign 64
1207.L_OP_GOTO_32: /* 0x2a */
1208/* File: armv5te/OP_GOTO_32.S */
1209    /*
1210     * Unconditional branch, 32-bit offset.
1211     *
1212     * The branch distance is a signed code-unit offset, which we need to
1213     * double to get a byte offset.
1214     *
1215     * Unlike most opcodes, this one is allowed to branch to itself, so
1216     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1217     * instruction doesn't affect the V flag, so we need to clear it
1218     * explicitly.
1219     */
1220    /* goto/32 +AAAAAAAA */
1221    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1222    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1223    cmp     ip, ip                      @ (clear V flag during stall)
1224    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1225    mov     r9, r0, asl #1              @ r9<- byte offset
1226    ble     common_backwardBranch       @ backward branch, do periodic checks
1227#if defined(WITH_JIT)
1228    GET_JIT_PROF_TABLE(r0)
1229    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1230    cmp     r0,#0
1231    bne     common_updateProfile
1232    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1233    GOTO_OPCODE(ip)                     @ jump to next instruction
1234#else
1235    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1237    GOTO_OPCODE(ip)                     @ jump to next instruction
1238#endif
1239
1240/* ------------------------------ */
1241    .balign 64
1242.L_OP_PACKED_SWITCH: /* 0x2b */
1243/* File: armv5te/OP_PACKED_SWITCH.S */
1244    /*
1245     * Handle a packed-switch or sparse-switch instruction.  In both cases
1246     * we decode it and hand it off to a helper function.
1247     *
1248     * We don't really expect backward branches in a switch statement, but
1249     * they're perfectly legal, so we check for them here.
1250     *
1251     * for: packed-switch, sparse-switch
1252     */
1253    /* op vAA, +BBBB */
1254    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1255    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1256    mov     r3, rINST, lsr #8           @ r3<- AA
1257    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1258    GET_VREG(r1, r3)                    @ r1<- vAA
1259    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1260    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1261    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1262    bmi     common_backwardBranch       @ backward branch, do periodic checks
1263    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1264#if defined(WITH_JIT)
1265    GET_JIT_PROF_TABLE(r0)
1266    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1267    cmp     r0,#0
1268    bne     common_updateProfile
1269    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1270    GOTO_OPCODE(ip)                     @ jump to next instruction
1271#else
1272    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1273    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1274    GOTO_OPCODE(ip)                     @ jump to next instruction
1275#endif
1276
1277/* ------------------------------ */
1278    .balign 64
1279.L_OP_SPARSE_SWITCH: /* 0x2c */
1280/* File: armv5te/OP_SPARSE_SWITCH.S */
1281/* File: armv5te/OP_PACKED_SWITCH.S */
1282    /*
1283     * Handle a packed-switch or sparse-switch instruction.  In both cases
1284     * we decode it and hand it off to a helper function.
1285     *
1286     * We don't really expect backward branches in a switch statement, but
1287     * they're perfectly legal, so we check for them here.
1288     *
1289     * for: packed-switch, sparse-switch
1290     */
1291    /* op vAA, +BBBB */
1292    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1293    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1294    mov     r3, rINST, lsr #8           @ r3<- AA
1295    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1296    GET_VREG(r1, r3)                    @ r1<- vAA
1297    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1298    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1299    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1300    bmi     common_backwardBranch       @ backward branch, do periodic checks
1301    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1302#if defined(WITH_JIT)
1303    GET_JIT_PROF_TABLE(r0)
1304    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1305    cmp     r0,#0
1306    bne     common_updateProfile
1307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1308    GOTO_OPCODE(ip)                     @ jump to next instruction
1309#else
1310    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1312    GOTO_OPCODE(ip)                     @ jump to next instruction
1313#endif
1314
1315
1316/* ------------------------------ */
1317    .balign 64
1318.L_OP_CMPL_FLOAT: /* 0x2d */
1319/* File: arm-vfp/OP_CMPL_FLOAT.S */
1320    /*
1321     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1322     * destination register based on the results of the comparison.
1323     *
1324     * int compare(x, y) {
1325     *     if (x == y) {
1326     *         return 0;
1327     *     } else if (x > y) {
1328     *         return 1;
1329     *     } else if (x < y) {
1330     *         return -1;
1331     *     } else {
1332     *         return -1;
1333     *     }
1334     * }
1335     */
1336    /* op vAA, vBB, vCC */
1337    FETCH(r0, 1)                        @ r0<- CCBB
1338    mov     r9, rINST, lsr #8           @ r9<- AA
1339    and     r2, r0, #255                @ r2<- BB
1340    mov     r3, r0, lsr #8              @ r3<- CC
1341    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1342    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1343    flds    s0, [r2]                    @ s0<- vBB
1344    flds    s1, [r3]                    @ s1<- vCC
1345    fcmpes  s0, s1                      @ compare (vBB, vCC)
1346    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1347    mvn     r0, #0                      @ r0<- -1 (default)
1348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1349    fmstat                              @ export status flags
1350    movgt   r0, #1                      @ (greater than) r1<- 1
1351    moveq   r0, #0                      @ (equal) r1<- 0
1352    b       .LOP_CMPL_FLOAT_finish          @ argh
1353
1354
1355/* ------------------------------ */
1356    .balign 64
1357.L_OP_CMPG_FLOAT: /* 0x2e */
1358/* File: arm-vfp/OP_CMPG_FLOAT.S */
1359    /*
1360     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1361     * destination register based on the results of the comparison.
1362     *
1363     * int compare(x, y) {
1364     *     if (x == y) {
1365     *         return 0;
1366     *     } else if (x < y) {
1367     *         return -1;
1368     *     } else if (x > y) {
1369     *         return 1;
1370     *     } else {
1371     *         return 1;
1372     *     }
1373     * }
1374     */
1375    /* op vAA, vBB, vCC */
1376    FETCH(r0, 1)                        @ r0<- CCBB
1377    mov     r9, rINST, lsr #8           @ r9<- AA
1378    and     r2, r0, #255                @ r2<- BB
1379    mov     r3, r0, lsr #8              @ r3<- CC
1380    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1381    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1382    flds    s0, [r2]                    @ s0<- vBB
1383    flds    s1, [r3]                    @ s1<- vCC
1384    fcmpes  s0, s1                      @ compare (vBB, vCC)
1385    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1386    mov     r0, #1                      @ r0<- 1 (default)
1387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1388    fmstat                              @ export status flags
1389    mvnmi   r0, #0                      @ (less than) r1<- -1
1390    moveq   r0, #0                      @ (equal) r1<- 0
1391    b       .LOP_CMPG_FLOAT_finish          @ argh
1392
1393
1394/* ------------------------------ */
1395    .balign 64
1396.L_OP_CMPL_DOUBLE: /* 0x2f */
1397/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1398    /*
1399     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1400     * destination register based on the results of the comparison.
1401     *
1402     * int compare(x, y) {
1403     *     if (x == y) {
1404     *         return 0;
1405     *     } else if (x > y) {
1406     *         return 1;
1407     *     } else if (x < y) {
1408     *         return -1;
1409     *     } else {
1410     *         return -1;
1411     *     }
1412     * }
1413     */
1414    /* op vAA, vBB, vCC */
1415    FETCH(r0, 1)                        @ r0<- CCBB
1416    mov     r9, rINST, lsr #8           @ r9<- AA
1417    and     r2, r0, #255                @ r2<- BB
1418    mov     r3, r0, lsr #8              @ r3<- CC
1419    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1420    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1421    fldd    d0, [r2]                    @ d0<- vBB
1422    fldd    d1, [r3]                    @ d1<- vCC
1423    fcmped  d0, d1                      @ compare (vBB, vCC)
1424    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1425    mvn     r0, #0                      @ r0<- -1 (default)
1426    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1427    fmstat                              @ export status flags
1428    movgt   r0, #1                      @ (greater than) r1<- 1
1429    moveq   r0, #0                      @ (equal) r1<- 0
1430    b       .LOP_CMPL_DOUBLE_finish          @ argh
1431
1432
1433/* ------------------------------ */
1434    .balign 64
1435.L_OP_CMPG_DOUBLE: /* 0x30 */
1436/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1437    /*
1438     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1439     * destination register based on the results of the comparison.
1440     *
1441     * int compare(x, y) {
1442     *     if (x == y) {
1443     *         return 0;
1444     *     } else if (x < y) {
1445     *         return -1;
1446     *     } else if (x > y) {
1447     *         return 1;
1448     *     } else {
1449     *         return 1;
1450     *     }
1451     * }
1452     */
1453    /* op vAA, vBB, vCC */
1454    FETCH(r0, 1)                        @ r0<- CCBB
1455    mov     r9, rINST, lsr #8           @ r9<- AA
1456    and     r2, r0, #255                @ r2<- BB
1457    mov     r3, r0, lsr #8              @ r3<- CC
1458    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1459    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1460    fldd    d0, [r2]                    @ d0<- vBB
1461    fldd    d1, [r3]                    @ d1<- vCC
1462    fcmped  d0, d1                      @ compare (vBB, vCC)
1463    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1464    mov     r0, #1                      @ r0<- 1 (default)
1465    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1466    fmstat                              @ export status flags
1467    mvnmi   r0, #0                      @ (less than) r1<- -1
1468    moveq   r0, #0                      @ (equal) r1<- 0
1469    b       .LOP_CMPG_DOUBLE_finish          @ argh
1470
1471
1472/* ------------------------------ */
1473    .balign 64
1474.L_OP_CMP_LONG: /* 0x31 */
1475/* File: armv5te/OP_CMP_LONG.S */
1476    /*
1477     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1478     * register based on the results of the comparison.
1479     *
1480     * We load the full values with LDM, but in practice many values could
1481     * be resolved by only looking at the high word.  This could be made
1482     * faster or slower by splitting the LDM into a pair of LDRs.
1483     *
1484     * If we just wanted to set condition flags, we could do this:
1485     *  subs    ip, r0, r2
1486     *  sbcs    ip, r1, r3
1487     *  subeqs  ip, r0, r2
1488     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1489     * integer value, which we can do with 2 conditional mov/mvn instructions
1490     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1491     * us a constant 5-cycle path plus a branch at the end to the
1492     * instruction epilogue code.  The multi-compare approach below needs
1493     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1494     * in the worst case (the 64-bit values are equal).
1495     */
1496    /* cmp-long vAA, vBB, vCC */
1497    FETCH(r0, 1)                        @ r0<- CCBB
1498    mov     r9, rINST, lsr #8           @ r9<- AA
1499    and     r2, r0, #255                @ r2<- BB
1500    mov     r3, r0, lsr #8              @ r3<- CC
1501    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1502    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1503    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1504    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1505    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1506    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1507    bgt     .LOP_CMP_LONG_greater
1508    subs    r1, r0, r2                  @ r1<- r0 - r2
1509    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1510    bne     .LOP_CMP_LONG_less
1511    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1512
1513/* ------------------------------ */
1514    .balign 64
1515.L_OP_IF_EQ: /* 0x32 */
1516/* File: armv6t2/OP_IF_EQ.S */
1517/* File: armv6t2/bincmp.S */
1518    /*
1519     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1520     * fragment that specifies the *reverse* comparison to perform, e.g.
1521     * for "if-le" you would use "gt".
1522     *
1523     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1524     */
1525    /* if-cmp vA, vB, +CCCC */
1526    mov     r1, rINST, lsr #12          @ r1<- B
1527    ubfx    r0, rINST, #8, #4           @ r0<- A
1528    GET_VREG(r3, r1)                    @ r3<- vB
1529    GET_VREG(r2, r0)                    @ r2<- vA
1530    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1531    cmp     r2, r3                      @ compare (vA, vB)
1532    bne  1f                      @ branch to 1 if comparison failed
1533    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1534    movs    r9, r9, asl #1              @ convert to bytes, check sign
1535    bmi     common_backwardBranch       @ yes, do periodic checks
15361:
1537#if defined(WITH_JIT)
1538    GET_JIT_PROF_TABLE(r0)
1539    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1540    b        common_testUpdateProfile
1541#else
1542    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1543    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1544    GOTO_OPCODE(ip)                     @ jump to next instruction
1545#endif
1546
1547
1548/* ------------------------------ */
1549    .balign 64
1550.L_OP_IF_NE: /* 0x33 */
1551/* File: armv6t2/OP_IF_NE.S */
1552/* File: armv6t2/bincmp.S */
1553    /*
1554     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1555     * fragment that specifies the *reverse* comparison to perform, e.g.
1556     * for "if-le" you would use "gt".
1557     *
1558     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1559     */
1560    /* if-cmp vA, vB, +CCCC */
1561    mov     r1, rINST, lsr #12          @ r1<- B
1562    ubfx    r0, rINST, #8, #4           @ r0<- A
1563    GET_VREG(r3, r1)                    @ r3<- vB
1564    GET_VREG(r2, r0)                    @ r2<- vA
1565    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1566    cmp     r2, r3                      @ compare (vA, vB)
1567    beq  1f                      @ branch to 1 if comparison failed
1568    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1569    movs    r9, r9, asl #1              @ convert to bytes, check sign
1570    bmi     common_backwardBranch       @ yes, do periodic checks
15711:
1572#if defined(WITH_JIT)
1573    GET_JIT_PROF_TABLE(r0)
1574    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1575    b        common_testUpdateProfile
1576#else
1577    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1578    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1579    GOTO_OPCODE(ip)                     @ jump to next instruction
1580#endif
1581
1582
1583/* ------------------------------ */
1584    .balign 64
1585.L_OP_IF_LT: /* 0x34 */
1586/* File: armv6t2/OP_IF_LT.S */
1587/* File: armv6t2/bincmp.S */
1588    /*
1589     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1590     * fragment that specifies the *reverse* comparison to perform, e.g.
1591     * for "if-le" you would use "gt".
1592     *
1593     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1594     */
1595    /* if-cmp vA, vB, +CCCC */
1596    mov     r1, rINST, lsr #12          @ r1<- B
1597    ubfx    r0, rINST, #8, #4           @ r0<- A
1598    GET_VREG(r3, r1)                    @ r3<- vB
1599    GET_VREG(r2, r0)                    @ r2<- vA
1600    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1601    cmp     r2, r3                      @ compare (vA, vB)
1602    bge  1f                      @ branch to 1 if comparison failed
1603    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1604    movs    r9, r9, asl #1              @ convert to bytes, check sign
1605    bmi     common_backwardBranch       @ yes, do periodic checks
16061:
1607#if defined(WITH_JIT)
1608    GET_JIT_PROF_TABLE(r0)
1609    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1610    b        common_testUpdateProfile
1611#else
1612    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1614    GOTO_OPCODE(ip)                     @ jump to next instruction
1615#endif
1616
1617
1618/* ------------------------------ */
1619    .balign 64
1620.L_OP_IF_GE: /* 0x35 */
1621/* File: armv6t2/OP_IF_GE.S */
1622/* File: armv6t2/bincmp.S */
1623    /*
1624     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1625     * fragment that specifies the *reverse* comparison to perform, e.g.
1626     * for "if-le" you would use "gt".
1627     *
1628     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1629     */
1630    /* if-cmp vA, vB, +CCCC */
1631    mov     r1, rINST, lsr #12          @ r1<- B
1632    ubfx    r0, rINST, #8, #4           @ r0<- A
1633    GET_VREG(r3, r1)                    @ r3<- vB
1634    GET_VREG(r2, r0)                    @ r2<- vA
1635    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1636    cmp     r2, r3                      @ compare (vA, vB)
1637    blt  1f                      @ branch to 1 if comparison failed
1638    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1639    movs    r9, r9, asl #1              @ convert to bytes, check sign
1640    bmi     common_backwardBranch       @ yes, do periodic checks
16411:
1642#if defined(WITH_JIT)
1643    GET_JIT_PROF_TABLE(r0)
1644    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1645    b        common_testUpdateProfile
1646#else
1647    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1648    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1649    GOTO_OPCODE(ip)                     @ jump to next instruction
1650#endif
1651
1652
1653/* ------------------------------ */
1654    .balign 64
1655.L_OP_IF_GT: /* 0x36 */
1656/* File: armv6t2/OP_IF_GT.S */
1657/* File: armv6t2/bincmp.S */
1658    /*
1659     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1660     * fragment that specifies the *reverse* comparison to perform, e.g.
1661     * for "if-le" you would use "gt".
1662     *
1663     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1664     */
1665    /* if-cmp vA, vB, +CCCC */
1666    mov     r1, rINST, lsr #12          @ r1<- B
1667    ubfx    r0, rINST, #8, #4           @ r0<- A
1668    GET_VREG(r3, r1)                    @ r3<- vB
1669    GET_VREG(r2, r0)                    @ r2<- vA
1670    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1671    cmp     r2, r3                      @ compare (vA, vB)
1672    ble  1f                      @ branch to 1 if comparison failed
1673    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1674    movs    r9, r9, asl #1              @ convert to bytes, check sign
1675    bmi     common_backwardBranch       @ yes, do periodic checks
16761:
1677#if defined(WITH_JIT)
1678    GET_JIT_PROF_TABLE(r0)
1679    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1680    b        common_testUpdateProfile
1681#else
1682    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1683    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1684    GOTO_OPCODE(ip)                     @ jump to next instruction
1685#endif
1686
1687
1688/* ------------------------------ */
1689    .balign 64
1690.L_OP_IF_LE: /* 0x37 */
1691/* File: armv6t2/OP_IF_LE.S */
1692/* File: armv6t2/bincmp.S */
1693    /*
1694     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1695     * fragment that specifies the *reverse* comparison to perform, e.g.
1696     * for "if-le" you would use "gt".
1697     *
1698     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1699     */
1700    /* if-cmp vA, vB, +CCCC */
1701    mov     r1, rINST, lsr #12          @ r1<- B
1702    ubfx    r0, rINST, #8, #4           @ r0<- A
1703    GET_VREG(r3, r1)                    @ r3<- vB
1704    GET_VREG(r2, r0)                    @ r2<- vA
1705    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1706    cmp     r2, r3                      @ compare (vA, vB)
1707    bgt  1f                      @ branch to 1 if comparison failed
1708    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1709    movs    r9, r9, asl #1              @ convert to bytes, check sign
1710    bmi     common_backwardBranch       @ yes, do periodic checks
17111:
1712#if defined(WITH_JIT)
1713    GET_JIT_PROF_TABLE(r0)
1714    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1715    b        common_testUpdateProfile
1716#else
1717    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1719    GOTO_OPCODE(ip)                     @ jump to next instruction
1720#endif
1721
1722
1723/* ------------------------------ */
1724    .balign 64
1725.L_OP_IF_EQZ: /* 0x38 */
1726/* File: armv5te/OP_IF_EQZ.S */
1727/* File: armv5te/zcmp.S */
1728    /*
1729     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1730     * fragment that specifies the *reverse* comparison to perform, e.g.
1731     * for "if-le" you would use "gt".
1732     *
1733     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1734     */
1735    /* if-cmp vAA, +BBBB */
1736    mov     r0, rINST, lsr #8           @ r0<- AA
1737    GET_VREG(r2, r0)                    @ r2<- vAA
1738    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1739    cmp     r2, #0                      @ compare (vA, 0)
1740    bne  1f                      @ branch to 1 if comparison failed
1741    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1742    movs    r9, r9, asl #1              @ convert to bytes, check sign
1743    bmi     common_backwardBranch       @ backward branch, do periodic checks
17441:
1745#if defined(WITH_JIT)
1746    GET_JIT_PROF_TABLE(r0)
1747    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1748    cmp     r0,#0
1749    bne     common_updateProfile
1750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1751    GOTO_OPCODE(ip)                     @ jump to next instruction
1752#else
1753    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1754    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1755    GOTO_OPCODE(ip)                     @ jump to next instruction
1756#endif
1757
1758
1759/* ------------------------------ */
1760    .balign 64
1761.L_OP_IF_NEZ: /* 0x39 */
1762/* File: armv5te/OP_IF_NEZ.S */
1763/* File: armv5te/zcmp.S */
1764    /*
1765     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1766     * fragment that specifies the *reverse* comparison to perform, e.g.
1767     * for "if-le" you would use "gt".
1768     *
1769     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1770     */
1771    /* if-cmp vAA, +BBBB */
1772    mov     r0, rINST, lsr #8           @ r0<- AA
1773    GET_VREG(r2, r0)                    @ r2<- vAA
1774    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1775    cmp     r2, #0                      @ compare (vA, 0)
1776    beq  1f                      @ branch to 1 if comparison failed
1777    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1778    movs    r9, r9, asl #1              @ convert to bytes, check sign
1779    bmi     common_backwardBranch       @ backward branch, do periodic checks
17801:
1781#if defined(WITH_JIT)
1782    GET_JIT_PROF_TABLE(r0)
1783    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1784    cmp     r0,#0
1785    bne     common_updateProfile
1786    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1787    GOTO_OPCODE(ip)                     @ jump to next instruction
1788#else
1789    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1790    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1791    GOTO_OPCODE(ip)                     @ jump to next instruction
1792#endif
1793
1794
1795/* ------------------------------ */
1796    .balign 64
1797.L_OP_IF_LTZ: /* 0x3a */
1798/* File: armv5te/OP_IF_LTZ.S */
1799/* File: armv5te/zcmp.S */
1800    /*
1801     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1802     * fragment that specifies the *reverse* comparison to perform, e.g.
1803     * for "if-le" you would use "gt".
1804     *
1805     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1806     */
1807    /* if-cmp vAA, +BBBB */
1808    mov     r0, rINST, lsr #8           @ r0<- AA
1809    GET_VREG(r2, r0)                    @ r2<- vAA
1810    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1811    cmp     r2, #0                      @ compare (vA, 0)
1812    bge  1f                      @ branch to 1 if comparison failed
1813    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1814    movs    r9, r9, asl #1              @ convert to bytes, check sign
1815    bmi     common_backwardBranch       @ backward branch, do periodic checks
18161:
1817#if defined(WITH_JIT)
1818    GET_JIT_PROF_TABLE(r0)
1819    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1820    cmp     r0,#0
1821    bne     common_updateProfile
1822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1823    GOTO_OPCODE(ip)                     @ jump to next instruction
1824#else
1825    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1827    GOTO_OPCODE(ip)                     @ jump to next instruction
1828#endif
1829
1830
1831/* ------------------------------ */
1832    .balign 64
1833.L_OP_IF_GEZ: /* 0x3b */
1834/* File: armv5te/OP_IF_GEZ.S */
1835/* File: armv5te/zcmp.S */
1836    /*
1837     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1838     * fragment that specifies the *reverse* comparison to perform, e.g.
1839     * for "if-le" you would use "gt".
1840     *
1841     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1842     */
1843    /* if-cmp vAA, +BBBB */
1844    mov     r0, rINST, lsr #8           @ r0<- AA
1845    GET_VREG(r2, r0)                    @ r2<- vAA
1846    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1847    cmp     r2, #0                      @ compare (vA, 0)
1848    blt  1f                      @ branch to 1 if comparison failed
1849    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1850    movs    r9, r9, asl #1              @ convert to bytes, check sign
1851    bmi     common_backwardBranch       @ backward branch, do periodic checks
18521:
1853#if defined(WITH_JIT)
1854    GET_JIT_PROF_TABLE(r0)
1855    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1856    cmp     r0,#0
1857    bne     common_updateProfile
1858    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1859    GOTO_OPCODE(ip)                     @ jump to next instruction
1860#else
1861    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1862    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1863    GOTO_OPCODE(ip)                     @ jump to next instruction
1864#endif
1865
1866
1867/* ------------------------------ */
1868    .balign 64
1869.L_OP_IF_GTZ: /* 0x3c */
1870/* File: armv5te/OP_IF_GTZ.S */
1871/* File: armv5te/zcmp.S */
1872    /*
1873     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1874     * fragment that specifies the *reverse* comparison to perform, e.g.
1875     * for "if-le" you would use "gt".
1876     *
1877     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1878     */
1879    /* if-cmp vAA, +BBBB */
1880    mov     r0, rINST, lsr #8           @ r0<- AA
1881    GET_VREG(r2, r0)                    @ r2<- vAA
1882    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1883    cmp     r2, #0                      @ compare (vA, 0)
1884    ble  1f                      @ branch to 1 if comparison failed
1885    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1886    movs    r9, r9, asl #1              @ convert to bytes, check sign
1887    bmi     common_backwardBranch       @ backward branch, do periodic checks
18881:
1889#if defined(WITH_JIT)
1890    GET_JIT_PROF_TABLE(r0)
1891    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1892    cmp     r0,#0
1893    bne     common_updateProfile
1894    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1895    GOTO_OPCODE(ip)                     @ jump to next instruction
1896#else
1897    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1899    GOTO_OPCODE(ip)                     @ jump to next instruction
1900#endif
1901
1902
1903/* ------------------------------ */
1904    .balign 64
1905.L_OP_IF_LEZ: /* 0x3d */
1906/* File: armv5te/OP_IF_LEZ.S */
1907/* File: armv5te/zcmp.S */
1908    /*
1909     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1910     * fragment that specifies the *reverse* comparison to perform, e.g.
1911     * for "if-le" you would use "gt".
1912     *
1913     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1914     */
1915    /* if-cmp vAA, +BBBB */
1916    mov     r0, rINST, lsr #8           @ r0<- AA
1917    GET_VREG(r2, r0)                    @ r2<- vAA
1918    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1919    cmp     r2, #0                      @ compare (vA, 0)
1920    bgt  1f                      @ branch to 1 if comparison failed
1921    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1922    movs    r9, r9, asl #1              @ convert to bytes, check sign
1923    bmi     common_backwardBranch       @ backward branch, do periodic checks
19241:
1925#if defined(WITH_JIT)
1926    GET_JIT_PROF_TABLE(r0)
1927    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1928    cmp     r0,#0
1929    bne     common_updateProfile
1930    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1931    GOTO_OPCODE(ip)                     @ jump to next instruction
1932#else
1933    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1935    GOTO_OPCODE(ip)                     @ jump to next instruction
1936#endif
1937
1938
1939/* ------------------------------ */
1940    .balign 64
1941.L_OP_UNUSED_3E: /* 0x3e */
1942/* File: armv5te/OP_UNUSED_3E.S */
1943/* File: armv5te/unused.S */
1944    bl      common_abort
1945
1946
1947/* ------------------------------ */
1948    .balign 64
1949.L_OP_UNUSED_3F: /* 0x3f */
1950/* File: armv5te/OP_UNUSED_3F.S */
1951/* File: armv5te/unused.S */
1952    bl      common_abort
1953
1954
1955/* ------------------------------ */
1956    .balign 64
1957.L_OP_UNUSED_40: /* 0x40 */
1958/* File: armv5te/OP_UNUSED_40.S */
1959/* File: armv5te/unused.S */
1960    bl      common_abort
1961
1962
1963/* ------------------------------ */
1964    .balign 64
1965.L_OP_UNUSED_41: /* 0x41 */
1966/* File: armv5te/OP_UNUSED_41.S */
1967/* File: armv5te/unused.S */
1968    bl      common_abort
1969
1970
1971/* ------------------------------ */
1972    .balign 64
1973.L_OP_UNUSED_42: /* 0x42 */
1974/* File: armv5te/OP_UNUSED_42.S */
1975/* File: armv5te/unused.S */
1976    bl      common_abort
1977
1978
1979/* ------------------------------ */
1980    .balign 64
1981.L_OP_UNUSED_43: /* 0x43 */
1982/* File: armv5te/OP_UNUSED_43.S */
1983/* File: armv5te/unused.S */
1984    bl      common_abort
1985
1986
1987/* ------------------------------ */
1988    .balign 64
1989.L_OP_AGET: /* 0x44 */
1990/* File: armv5te/OP_AGET.S */
1991    /*
1992     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1993     *
1994     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1995     * instructions.  We use a pair of FETCH_Bs instead.
1996     *
1997     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1998     */
1999    /* op vAA, vBB, vCC */
2000    FETCH_B(r2, 1, 0)                   @ r2<- BB
2001    mov     r9, rINST, lsr #8           @ r9<- AA
2002    FETCH_B(r3, 1, 1)                   @ r3<- CC
2003    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2004    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2005    cmp     r0, #0                      @ null array object?
2006    beq     common_errNullObject        @ yes, bail
2007    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2008    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2009    cmp     r1, r3                      @ compare unsigned index, length
2010    bcs     common_errArrayIndex        @ index >= length, bail
2011    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2012    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2014    SET_VREG(r2, r9)                    @ vAA<- r2
2015    GOTO_OPCODE(ip)                     @ jump to next instruction
2016
2017/* ------------------------------ */
2018    .balign 64
2019.L_OP_AGET_WIDE: /* 0x45 */
2020/* File: armv5te/OP_AGET_WIDE.S */
2021    /*
2022     * Array get, 64 bits.  vAA <- vBB[vCC].
2023     *
2024     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2025     */
2026    /* aget-wide vAA, vBB, vCC */
2027    FETCH(r0, 1)                        @ r0<- CCBB
2028    mov     r9, rINST, lsr #8           @ r9<- AA
2029    and     r2, r0, #255                @ r2<- BB
2030    mov     r3, r0, lsr #8              @ r3<- CC
2031    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2032    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2033    cmp     r0, #0                      @ null array object?
2034    beq     common_errNullObject        @ yes, bail
2035    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2036    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2037    cmp     r1, r3                      @ compare unsigned index, length
2038    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2039    b       common_errArrayIndex        @ index >= length, bail
2040    @ May want to swap the order of these two branches depending on how the
2041    @ branch prediction (if any) handles conditional forward branches vs.
2042    @ unconditional forward branches.
2043
2044/* ------------------------------ */
2045    .balign 64
2046.L_OP_AGET_OBJECT: /* 0x46 */
2047/* File: armv5te/OP_AGET_OBJECT.S */
2048/* File: armv5te/OP_AGET.S */
2049    /*
2050     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2051     *
2052     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2053     * instructions.  We use a pair of FETCH_Bs instead.
2054     *
2055     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2056     */
2057    /* op vAA, vBB, vCC */
2058    FETCH_B(r2, 1, 0)                   @ r2<- BB
2059    mov     r9, rINST, lsr #8           @ r9<- AA
2060    FETCH_B(r3, 1, 1)                   @ r3<- CC
2061    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2062    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2063    cmp     r0, #0                      @ null array object?
2064    beq     common_errNullObject        @ yes, bail
2065    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2066    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2067    cmp     r1, r3                      @ compare unsigned index, length
2068    bcs     common_errArrayIndex        @ index >= length, bail
2069    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2070    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2071    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2072    SET_VREG(r2, r9)                    @ vAA<- r2
2073    GOTO_OPCODE(ip)                     @ jump to next instruction
2074
2075
2076/* ------------------------------ */
2077    .balign 64
2078.L_OP_AGET_BOOLEAN: /* 0x47 */
2079/* File: armv5te/OP_AGET_BOOLEAN.S */
2080/* File: armv5te/OP_AGET.S */
2081    /*
2082     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2083     *
2084     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2085     * instructions.  We use a pair of FETCH_Bs instead.
2086     *
2087     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2088     */
2089    /* op vAA, vBB, vCC */
2090    FETCH_B(r2, 1, 0)                   @ r2<- BB
2091    mov     r9, rINST, lsr #8           @ r9<- AA
2092    FETCH_B(r3, 1, 1)                   @ r3<- CC
2093    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2094    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2095    cmp     r0, #0                      @ null array object?
2096    beq     common_errNullObject        @ yes, bail
2097    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2098    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2099    cmp     r1, r3                      @ compare unsigned index, length
2100    bcs     common_errArrayIndex        @ index >= length, bail
2101    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2102    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2103    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2104    SET_VREG(r2, r9)                    @ vAA<- r2
2105    GOTO_OPCODE(ip)                     @ jump to next instruction
2106
2107
2108/* ------------------------------ */
2109    .balign 64
2110.L_OP_AGET_BYTE: /* 0x48 */
2111/* File: armv5te/OP_AGET_BYTE.S */
2112/* File: armv5te/OP_AGET.S */
2113    /*
2114     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2115     *
2116     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2117     * instructions.  We use a pair of FETCH_Bs instead.
2118     *
2119     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2120     */
2121    /* op vAA, vBB, vCC */
2122    FETCH_B(r2, 1, 0)                   @ r2<- BB
2123    mov     r9, rINST, lsr #8           @ r9<- AA
2124    FETCH_B(r3, 1, 1)                   @ r3<- CC
2125    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2126    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2127    cmp     r0, #0                      @ null array object?
2128    beq     common_errNullObject        @ yes, bail
2129    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2130    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2131    cmp     r1, r3                      @ compare unsigned index, length
2132    bcs     common_errArrayIndex        @ index >= length, bail
2133    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2134    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2136    SET_VREG(r2, r9)                    @ vAA<- r2
2137    GOTO_OPCODE(ip)                     @ jump to next instruction
2138
2139
2140/* ------------------------------ */
2141    .balign 64
2142.L_OP_AGET_CHAR: /* 0x49 */
2143/* File: armv5te/OP_AGET_CHAR.S */
2144/* File: armv5te/OP_AGET.S */
2145    /*
2146     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2147     *
2148     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2149     * instructions.  We use a pair of FETCH_Bs instead.
2150     *
2151     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2152     */
2153    /* op vAA, vBB, vCC */
2154    FETCH_B(r2, 1, 0)                   @ r2<- BB
2155    mov     r9, rINST, lsr #8           @ r9<- AA
2156    FETCH_B(r3, 1, 1)                   @ r3<- CC
2157    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2158    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2159    cmp     r0, #0                      @ null array object?
2160    beq     common_errNullObject        @ yes, bail
2161    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2162    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2163    cmp     r1, r3                      @ compare unsigned index, length
2164    bcs     common_errArrayIndex        @ index >= length, bail
2165    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2166    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2168    SET_VREG(r2, r9)                    @ vAA<- r2
2169    GOTO_OPCODE(ip)                     @ jump to next instruction
2170
2171
2172/* ------------------------------ */
2173    .balign 64
2174.L_OP_AGET_SHORT: /* 0x4a */
2175/* File: armv5te/OP_AGET_SHORT.S */
2176/* File: armv5te/OP_AGET.S */
2177    /*
2178     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2179     *
2180     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2181     * instructions.  We use a pair of FETCH_Bs instead.
2182     *
2183     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2184     */
2185    /* op vAA, vBB, vCC */
2186    FETCH_B(r2, 1, 0)                   @ r2<- BB
2187    mov     r9, rINST, lsr #8           @ r9<- AA
2188    FETCH_B(r3, 1, 1)                   @ r3<- CC
2189    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2190    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2191    cmp     r0, #0                      @ null array object?
2192    beq     common_errNullObject        @ yes, bail
2193    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2194    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2195    cmp     r1, r3                      @ compare unsigned index, length
2196    bcs     common_errArrayIndex        @ index >= length, bail
2197    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2198    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2199    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2200    SET_VREG(r2, r9)                    @ vAA<- r2
2201    GOTO_OPCODE(ip)                     @ jump to next instruction
2202
2203
2204/* ------------------------------ */
2205    .balign 64
2206.L_OP_APUT: /* 0x4b */
2207/* File: armv5te/OP_APUT.S */
2208    /*
2209     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2210     *
2211     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2212     * instructions.  We use a pair of FETCH_Bs instead.
2213     *
2214     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2215     */
2216    /* op vAA, vBB, vCC */
2217    FETCH_B(r2, 1, 0)                   @ r2<- BB
2218    mov     r9, rINST, lsr #8           @ r9<- AA
2219    FETCH_B(r3, 1, 1)                   @ r3<- CC
2220    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2221    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2222    cmp     r0, #0                      @ null array object?
2223    beq     common_errNullObject        @ yes, bail
2224    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2225    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2226    cmp     r1, r3                      @ compare unsigned index, length
2227    bcs     common_errArrayIndex        @ index >= length, bail
2228    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2229    GET_VREG(r2, r9)                    @ r2<- vAA
2230    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2231    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2232    GOTO_OPCODE(ip)                     @ jump to next instruction
2233
2234/* ------------------------------ */
2235    .balign 64
2236.L_OP_APUT_WIDE: /* 0x4c */
2237/* File: armv5te/OP_APUT_WIDE.S */
2238    /*
2239     * Array put, 64 bits.  vBB[vCC] <- vAA.
2240     *
2241     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2242     */
2243    /* aput-wide vAA, vBB, vCC */
2244    FETCH(r0, 1)                        @ r0<- CCBB
2245    mov     r9, rINST, lsr #8           @ r9<- AA
2246    and     r2, r0, #255                @ r2<- BB
2247    mov     r3, r0, lsr #8              @ r3<- CC
2248    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2249    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2250    cmp     r0, #0                      @ null array object?
2251    beq     common_errNullObject        @ yes, bail
2252    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2253    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2254    cmp     r1, r3                      @ compare unsigned index, length
2255    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2256    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2257    b       common_errArrayIndex        @ index >= length, bail
2258    @ May want to swap the order of these two branches depending on how the
2259    @ branch prediction (if any) handles conditional forward branches vs.
2260    @ unconditional forward branches.
2261
2262/* ------------------------------ */
2263    .balign 64
2264.L_OP_APUT_OBJECT: /* 0x4d */
2265/* File: armv5te/OP_APUT_OBJECT.S */
2266    /*
2267     * Store an object into an array.  vBB[vCC] <- vAA.
2268     *
2269     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2270     * instructions.  We use a pair of FETCH_Bs instead.
2271     */
2272    /* op vAA, vBB, vCC */
2273    FETCH(r0, 1)                        @ r0<- CCBB
2274    mov     r9, rINST, lsr #8           @ r9<- AA
2275    and     r2, r0, #255                @ r2<- BB
2276    mov     r3, r0, lsr #8              @ r3<- CC
2277    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2278    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2279    cmp     rINST, #0                   @ null array object?
2280    GET_VREG(r9, r9)                    @ r9<- vAA
2281    beq     common_errNullObject        @ yes, bail
2282    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2283    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
2284    cmp     r0, r3                      @ compare unsigned index, length
2285    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2286    b       common_errArrayIndex        @ index >= length, bail
2287
2288
2289/* ------------------------------ */
2290    .balign 64
2291.L_OP_APUT_BOOLEAN: /* 0x4e */
2292/* File: armv5te/OP_APUT_BOOLEAN.S */
2293/* File: armv5te/OP_APUT.S */
2294    /*
2295     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2296     *
2297     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2298     * instructions.  We use a pair of FETCH_Bs instead.
2299     *
2300     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2301     */
2302    /* op vAA, vBB, vCC */
2303    FETCH_B(r2, 1, 0)                   @ r2<- BB
2304    mov     r9, rINST, lsr #8           @ r9<- AA
2305    FETCH_B(r3, 1, 1)                   @ r3<- CC
2306    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2307    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2308    cmp     r0, #0                      @ null array object?
2309    beq     common_errNullObject        @ yes, bail
2310    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2311    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2312    cmp     r1, r3                      @ compare unsigned index, length
2313    bcs     common_errArrayIndex        @ index >= length, bail
2314    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2315    GET_VREG(r2, r9)                    @ r2<- vAA
2316    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2317    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2318    GOTO_OPCODE(ip)                     @ jump to next instruction
2319
2320
2321/* ------------------------------ */
2322    .balign 64
2323.L_OP_APUT_BYTE: /* 0x4f */
2324/* File: armv5te/OP_APUT_BYTE.S */
2325/* File: armv5te/OP_APUT.S */
2326    /*
2327     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2328     *
2329     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2330     * instructions.  We use a pair of FETCH_Bs instead.
2331     *
2332     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2333     */
2334    /* op vAA, vBB, vCC */
2335    FETCH_B(r2, 1, 0)                   @ r2<- BB
2336    mov     r9, rINST, lsr #8           @ r9<- AA
2337    FETCH_B(r3, 1, 1)                   @ r3<- CC
2338    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2339    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2340    cmp     r0, #0                      @ null array object?
2341    beq     common_errNullObject        @ yes, bail
2342    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2343    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2344    cmp     r1, r3                      @ compare unsigned index, length
2345    bcs     common_errArrayIndex        @ index >= length, bail
2346    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2347    GET_VREG(r2, r9)                    @ r2<- vAA
2348    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2349    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2350    GOTO_OPCODE(ip)                     @ jump to next instruction
2351
2352
2353/* ------------------------------ */
2354    .balign 64
2355.L_OP_APUT_CHAR: /* 0x50 */
2356/* File: armv5te/OP_APUT_CHAR.S */
2357/* File: armv5te/OP_APUT.S */
2358    /*
2359     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2360     *
2361     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2362     * instructions.  We use a pair of FETCH_Bs instead.
2363     *
2364     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2365     */
2366    /* op vAA, vBB, vCC */
2367    FETCH_B(r2, 1, 0)                   @ r2<- BB
2368    mov     r9, rINST, lsr #8           @ r9<- AA
2369    FETCH_B(r3, 1, 1)                   @ r3<- CC
2370    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2371    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2372    cmp     r0, #0                      @ null array object?
2373    beq     common_errNullObject        @ yes, bail
2374    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2375    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2376    cmp     r1, r3                      @ compare unsigned index, length
2377    bcs     common_errArrayIndex        @ index >= length, bail
2378    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2379    GET_VREG(r2, r9)                    @ r2<- vAA
2380    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2381    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2382    GOTO_OPCODE(ip)                     @ jump to next instruction
2383
2384
2385/* ------------------------------ */
2386    .balign 64
2387.L_OP_APUT_SHORT: /* 0x51 */
2388/* File: armv5te/OP_APUT_SHORT.S */
2389/* File: armv5te/OP_APUT.S */
2390    /*
2391     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2392     *
2393     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2394     * instructions.  We use a pair of FETCH_Bs instead.
2395     *
2396     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2397     */
2398    /* op vAA, vBB, vCC */
2399    FETCH_B(r2, 1, 0)                   @ r2<- BB
2400    mov     r9, rINST, lsr #8           @ r9<- AA
2401    FETCH_B(r3, 1, 1)                   @ r3<- CC
2402    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2403    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2404    cmp     r0, #0                      @ null array object?
2405    beq     common_errNullObject        @ yes, bail
2406    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2407    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2408    cmp     r1, r3                      @ compare unsigned index, length
2409    bcs     common_errArrayIndex        @ index >= length, bail
2410    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2411    GET_VREG(r2, r9)                    @ r2<- vAA
2412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2413    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2414    GOTO_OPCODE(ip)                     @ jump to next instruction
2415
2416
2417/* ------------------------------ */
2418    .balign 64
2419.L_OP_IGET: /* 0x52 */
2420/* File: armv6t2/OP_IGET.S */
2421    /*
2422     * General 32-bit instance field get.
2423     *
2424     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2425     */
2426    /* op vA, vB, field@CCCC */
2427    mov     r0, rINST, lsr #12          @ r0<- B
2428    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2429    FETCH(r1, 1)                        @ r1<- field ref CCCC
2430    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2431    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2432    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2433    cmp     r0, #0                      @ is resolved entry null?
2434    bne     .LOP_IGET_finish          @ no, already resolved
24358:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2436    EXPORT_PC()                         @ resolve() could throw
2437    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2438    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2439    cmp     r0, #0
2440    bne     .LOP_IGET_finish
2441    b       common_exceptionThrown
2442
2443/* ------------------------------ */
2444    .balign 64
2445.L_OP_IGET_WIDE: /* 0x53 */
2446/* File: armv6t2/OP_IGET_WIDE.S */
2447    /*
2448     * Wide 32-bit instance field get.
2449     */
2450    /* iget-wide vA, vB, field@CCCC */
2451    mov     r0, rINST, lsr #12          @ r0<- B
2452    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2453    FETCH(r1, 1)                        @ r1<- field ref CCCC
2454    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2455    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2456    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2457    cmp     r0, #0                      @ is resolved entry null?
2458    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24598:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2460    EXPORT_PC()                         @ resolve() could throw
2461    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2462    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2463    cmp     r0, #0
2464    bne     .LOP_IGET_WIDE_finish
2465    b       common_exceptionThrown
2466
2467/* ------------------------------ */
2468    .balign 64
2469.L_OP_IGET_OBJECT: /* 0x54 */
2470/* File: armv5te/OP_IGET_OBJECT.S */
2471/* File: armv5te/OP_IGET.S */
2472    /*
2473     * General 32-bit instance field get.
2474     *
2475     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2476     */
2477    /* op vA, vB, field@CCCC */
2478    mov     r0, rINST, lsr #12          @ r0<- B
2479    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2480    FETCH(r1, 1)                        @ r1<- field ref CCCC
2481    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2482    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2483    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2484    cmp     r0, #0                      @ is resolved entry null?
2485    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24868:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2487    EXPORT_PC()                         @ resolve() could throw
2488    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2489    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2490    cmp     r0, #0
2491    bne     .LOP_IGET_OBJECT_finish
2492    b       common_exceptionThrown
2493
2494
2495/* ------------------------------ */
2496    .balign 64
2497.L_OP_IGET_BOOLEAN: /* 0x55 */
2498/* File: armv5te/OP_IGET_BOOLEAN.S */
2499@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2500/* File: armv5te/OP_IGET.S */
2501    /*
2502     * General 32-bit instance field get.
2503     *
2504     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2505     */
2506    /* op vA, vB, field@CCCC */
2507    mov     r0, rINST, lsr #12          @ r0<- B
2508    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2509    FETCH(r1, 1)                        @ r1<- field ref CCCC
2510    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2511    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2512    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2513    cmp     r0, #0                      @ is resolved entry null?
2514    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25158:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2516    EXPORT_PC()                         @ resolve() could throw
2517    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2518    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2519    cmp     r0, #0
2520    bne     .LOP_IGET_BOOLEAN_finish
2521    b       common_exceptionThrown
2522
2523
2524/* ------------------------------ */
2525    .balign 64
2526.L_OP_IGET_BYTE: /* 0x56 */
2527/* File: armv5te/OP_IGET_BYTE.S */
2528@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2529/* File: armv5te/OP_IGET.S */
2530    /*
2531     * General 32-bit instance field get.
2532     *
2533     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2534     */
2535    /* op vA, vB, field@CCCC */
2536    mov     r0, rINST, lsr #12          @ r0<- B
2537    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2538    FETCH(r1, 1)                        @ r1<- field ref CCCC
2539    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2540    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2541    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2542    cmp     r0, #0                      @ is resolved entry null?
2543    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25448:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2545    EXPORT_PC()                         @ resolve() could throw
2546    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2547    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2548    cmp     r0, #0
2549    bne     .LOP_IGET_BYTE_finish
2550    b       common_exceptionThrown
2551
2552
2553/* ------------------------------ */
2554    .balign 64
2555.L_OP_IGET_CHAR: /* 0x57 */
2556/* File: armv5te/OP_IGET_CHAR.S */
2557@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2558/* File: armv5te/OP_IGET.S */
2559    /*
2560     * General 32-bit instance field get.
2561     *
2562     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2563     */
2564    /* op vA, vB, field@CCCC */
2565    mov     r0, rINST, lsr #12          @ r0<- B
2566    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2567    FETCH(r1, 1)                        @ r1<- field ref CCCC
2568    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2569    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2570    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2571    cmp     r0, #0                      @ is resolved entry null?
2572    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25738:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2574    EXPORT_PC()                         @ resolve() could throw
2575    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2576    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2577    cmp     r0, #0
2578    bne     .LOP_IGET_CHAR_finish
2579    b       common_exceptionThrown
2580
2581
2582/* ------------------------------ */
2583    .balign 64
2584.L_OP_IGET_SHORT: /* 0x58 */
2585/* File: armv5te/OP_IGET_SHORT.S */
2586@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2587/* File: armv5te/OP_IGET.S */
2588    /*
2589     * General 32-bit instance field get.
2590     *
2591     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2592     */
2593    /* op vA, vB, field@CCCC */
2594    mov     r0, rINST, lsr #12          @ r0<- B
2595    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2596    FETCH(r1, 1)                        @ r1<- field ref CCCC
2597    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2598    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2599    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2600    cmp     r0, #0                      @ is resolved entry null?
2601    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26028:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2603    EXPORT_PC()                         @ resolve() could throw
2604    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2605    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2606    cmp     r0, #0
2607    bne     .LOP_IGET_SHORT_finish
2608    b       common_exceptionThrown
2609
2610
2611/* ------------------------------ */
2612    .balign 64
2613.L_OP_IPUT: /* 0x59 */
2614/* File: armv6t2/OP_IPUT.S */
2615    /*
2616     * General 32-bit instance field put.
2617     *
2618     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2619     */
2620    /* op vA, vB, field@CCCC */
2621    mov     r0, rINST, lsr #12          @ r0<- B
2622    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2623    FETCH(r1, 1)                        @ r1<- field ref CCCC
2624    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2625    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2626    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2627    cmp     r0, #0                      @ is resolved entry null?
2628    bne     .LOP_IPUT_finish          @ no, already resolved
26298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2630    EXPORT_PC()                         @ resolve() could throw
2631    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2632    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2633    cmp     r0, #0                      @ success?
2634    bne     .LOP_IPUT_finish          @ yes, finish up
2635    b       common_exceptionThrown
2636
2637/* ------------------------------ */
2638    .balign 64
2639.L_OP_IPUT_WIDE: /* 0x5a */
2640/* File: armv6t2/OP_IPUT_WIDE.S */
2641    /* iput-wide vA, vB, field@CCCC */
2642    mov     r0, rINST, lsr #12          @ r0<- B
2643    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2644    FETCH(r1, 1)                        @ r1<- field ref CCCC
2645    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2646    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2647    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2648    cmp     r0, #0                      @ is resolved entry null?
2649    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26508:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2651    EXPORT_PC()                         @ resolve() could throw
2652    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2653    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2654    cmp     r0, #0                      @ success?
2655    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2656    b       common_exceptionThrown
2657
2658/* ------------------------------ */
2659    .balign 64
2660.L_OP_IPUT_OBJECT: /* 0x5b */
2661/* File: armv5te/OP_IPUT_OBJECT.S */
2662    /*
2663     * 32-bit instance field put.
2664     *
2665     * for: iput-object, iput-object-volatile
2666     */
2667    /* op vA, vB, field@CCCC */
2668    mov     r0, rINST, lsr #12          @ r0<- B
2669    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2670    FETCH(r1, 1)                        @ r1<- field ref CCCC
2671    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2672    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2673    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2674    cmp     r0, #0                      @ is resolved entry null?
2675    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26768:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2677    EXPORT_PC()                         @ resolve() could throw
2678    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2679    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2680    cmp     r0, #0                      @ success?
2681    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2682    b       common_exceptionThrown
2683
2684/* ------------------------------ */
2685    .balign 64
2686.L_OP_IPUT_BOOLEAN: /* 0x5c */
2687/* File: armv5te/OP_IPUT_BOOLEAN.S */
2688@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2689/* File: armv5te/OP_IPUT.S */
2690    /*
2691     * General 32-bit instance field put.
2692     *
2693     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2694     */
2695    /* op vA, vB, field@CCCC */
2696    mov     r0, rINST, lsr #12          @ r0<- B
2697    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2698    FETCH(r1, 1)                        @ r1<- field ref CCCC
2699    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2700    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2701    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2702    cmp     r0, #0                      @ is resolved entry null?
2703    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27048:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2705    EXPORT_PC()                         @ resolve() could throw
2706    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2707    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2708    cmp     r0, #0                      @ success?
2709    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2710    b       common_exceptionThrown
2711
2712
2713/* ------------------------------ */
2714    .balign 64
2715.L_OP_IPUT_BYTE: /* 0x5d */
2716/* File: armv5te/OP_IPUT_BYTE.S */
2717@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2718/* File: armv5te/OP_IPUT.S */
2719    /*
2720     * General 32-bit instance field put.
2721     *
2722     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2723     */
2724    /* op vA, vB, field@CCCC */
2725    mov     r0, rINST, lsr #12          @ r0<- B
2726    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2727    FETCH(r1, 1)                        @ r1<- field ref CCCC
2728    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2729    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2730    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2731    cmp     r0, #0                      @ is resolved entry null?
2732    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27338:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2734    EXPORT_PC()                         @ resolve() could throw
2735    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2736    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2737    cmp     r0, #0                      @ success?
2738    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2739    b       common_exceptionThrown
2740
2741
2742/* ------------------------------ */
2743    .balign 64
2744.L_OP_IPUT_CHAR: /* 0x5e */
2745/* File: armv5te/OP_IPUT_CHAR.S */
2746@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2747/* File: armv5te/OP_IPUT.S */
2748    /*
2749     * General 32-bit instance field put.
2750     *
2751     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2752     */
2753    /* op vA, vB, field@CCCC */
2754    mov     r0, rINST, lsr #12          @ r0<- B
2755    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2756    FETCH(r1, 1)                        @ r1<- field ref CCCC
2757    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2758    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2759    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2760    cmp     r0, #0                      @ is resolved entry null?
2761    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27628:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2763    EXPORT_PC()                         @ resolve() could throw
2764    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2765    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2766    cmp     r0, #0                      @ success?
2767    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2768    b       common_exceptionThrown
2769
2770
2771/* ------------------------------ */
2772    .balign 64
2773.L_OP_IPUT_SHORT: /* 0x5f */
2774/* File: armv5te/OP_IPUT_SHORT.S */
2775@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2776/* File: armv5te/OP_IPUT.S */
2777    /*
2778     * General 32-bit instance field put.
2779     *
2780     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2781     */
2782    /* op vA, vB, field@CCCC */
2783    mov     r0, rINST, lsr #12          @ r0<- B
2784    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2785    FETCH(r1, 1)                        @ r1<- field ref CCCC
2786    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2787    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2788    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2789    cmp     r0, #0                      @ is resolved entry null?
2790    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27918:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2792    EXPORT_PC()                         @ resolve() could throw
2793    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2794    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2795    cmp     r0, #0                      @ success?
2796    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2797    b       common_exceptionThrown
2798
2799
2800/* ------------------------------ */
2801    .balign 64
2802.L_OP_SGET: /* 0x60 */
2803/* File: armv5te/OP_SGET.S */
2804    /*
2805     * General 32-bit SGET handler.
2806     *
2807     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2808     */
2809    /* op vAA, field@BBBB */
2810    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2811    FETCH(r1, 1)                        @ r1<- field ref BBBB
2812    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2813    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2814    cmp     r0, #0                      @ is resolved entry null?
2815    beq     .LOP_SGET_resolve         @ yes, do resolve
2816.LOP_SGET_finish: @ field ptr in r0
2817    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2818    @ no-op                             @ acquiring load
2819    mov     r2, rINST, lsr #8           @ r2<- AA
2820    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2821    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2823    GOTO_OPCODE(ip)                     @ jump to next instruction
2824
2825/* ------------------------------ */
2826    .balign 64
2827.L_OP_SGET_WIDE: /* 0x61 */
2828/* File: armv5te/OP_SGET_WIDE.S */
2829    /*
2830     * 64-bit SGET handler.
2831     */
2832    /* sget-wide vAA, field@BBBB */
2833    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2834    FETCH(r1, 1)                        @ r1<- field ref BBBB
2835    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2836    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2837    cmp     r0, #0                      @ is resolved entry null?
2838    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2839.LOP_SGET_WIDE_finish:
2840    mov     r9, rINST, lsr #8           @ r9<- AA
2841    .if 0
2842    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2843    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2844    .else
2845    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2846    .endif
2847    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2848    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2849    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2850    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2851    GOTO_OPCODE(ip)                     @ jump to next instruction
2852
2853/* ------------------------------ */
2854    .balign 64
2855.L_OP_SGET_OBJECT: /* 0x62 */
2856/* File: armv5te/OP_SGET_OBJECT.S */
2857/* File: armv5te/OP_SGET.S */
2858    /*
2859     * General 32-bit SGET handler.
2860     *
2861     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2862     */
2863    /* op vAA, field@BBBB */
2864    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2865    FETCH(r1, 1)                        @ r1<- field ref BBBB
2866    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2867    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2868    cmp     r0, #0                      @ is resolved entry null?
2869    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2870.LOP_SGET_OBJECT_finish: @ field ptr in r0
2871    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2872    @ no-op                             @ acquiring load
2873    mov     r2, rINST, lsr #8           @ r2<- AA
2874    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2875    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2876    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2877    GOTO_OPCODE(ip)                     @ jump to next instruction
2878
2879
2880/* ------------------------------ */
2881    .balign 64
2882.L_OP_SGET_BOOLEAN: /* 0x63 */
2883/* File: armv5te/OP_SGET_BOOLEAN.S */
2884/* File: armv5te/OP_SGET.S */
2885    /*
2886     * General 32-bit SGET handler.
2887     *
2888     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2889     */
2890    /* op vAA, field@BBBB */
2891    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2892    FETCH(r1, 1)                        @ r1<- field ref BBBB
2893    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2894    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2895    cmp     r0, #0                      @ is resolved entry null?
2896    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2897.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2898    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2899    @ no-op                             @ acquiring load
2900    mov     r2, rINST, lsr #8           @ r2<- AA
2901    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2902    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2904    GOTO_OPCODE(ip)                     @ jump to next instruction
2905
2906
2907/* ------------------------------ */
2908    .balign 64
2909.L_OP_SGET_BYTE: /* 0x64 */
2910/* File: armv5te/OP_SGET_BYTE.S */
2911/* File: armv5te/OP_SGET.S */
2912    /*
2913     * General 32-bit SGET handler.
2914     *
2915     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2916     */
2917    /* op vAA, field@BBBB */
2918    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2919    FETCH(r1, 1)                        @ r1<- field ref BBBB
2920    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2921    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2922    cmp     r0, #0                      @ is resolved entry null?
2923    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2924.LOP_SGET_BYTE_finish: @ field ptr in r0
2925    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2926    @ no-op                             @ acquiring load
2927    mov     r2, rINST, lsr #8           @ r2<- AA
2928    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2929    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2930    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2931    GOTO_OPCODE(ip)                     @ jump to next instruction
2932
2933
2934/* ------------------------------ */
2935    .balign 64
2936.L_OP_SGET_CHAR: /* 0x65 */
2937/* File: armv5te/OP_SGET_CHAR.S */
2938/* File: armv5te/OP_SGET.S */
2939    /*
2940     * General 32-bit SGET handler.
2941     *
2942     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2943     */
2944    /* op vAA, field@BBBB */
2945    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2946    FETCH(r1, 1)                        @ r1<- field ref BBBB
2947    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2948    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2949    cmp     r0, #0                      @ is resolved entry null?
2950    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2951.LOP_SGET_CHAR_finish: @ field ptr in r0
2952    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2953    @ no-op                             @ acquiring load
2954    mov     r2, rINST, lsr #8           @ r2<- AA
2955    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2956    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2958    GOTO_OPCODE(ip)                     @ jump to next instruction
2959
2960
2961/* ------------------------------ */
2962    .balign 64
2963.L_OP_SGET_SHORT: /* 0x66 */
2964/* File: armv5te/OP_SGET_SHORT.S */
2965/* File: armv5te/OP_SGET.S */
2966    /*
2967     * General 32-bit SGET handler.
2968     *
2969     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2970     */
2971    /* op vAA, field@BBBB */
2972    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2973    FETCH(r1, 1)                        @ r1<- field ref BBBB
2974    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2975    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2976    cmp     r0, #0                      @ is resolved entry null?
2977    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2978.LOP_SGET_SHORT_finish: @ field ptr in r0
2979    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2980    @ no-op                             @ acquiring load
2981    mov     r2, rINST, lsr #8           @ r2<- AA
2982    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2983    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2984    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2985    GOTO_OPCODE(ip)                     @ jump to next instruction
2986
2987
2988/* ------------------------------ */
2989    .balign 64
2990.L_OP_SPUT: /* 0x67 */
2991/* File: armv5te/OP_SPUT.S */
2992    /*
2993     * General 32-bit SPUT handler.
2994     *
2995     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2996     */
2997    /* op vAA, field@BBBB */
2998    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2999    FETCH(r1, 1)                        @ r1<- field ref BBBB
3000    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3001    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3002    cmp     r0, #0                      @ is resolved entry null?
3003    beq     .LOP_SPUT_resolve         @ yes, do resolve
3004.LOP_SPUT_finish:   @ field ptr in r0
3005    mov     r2, rINST, lsr #8           @ r2<- AA
3006    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3007    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3008    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3009    @ no-op                             @ releasing store
3010    str     r1, [r0, #offStaticField_value] @ field<- vAA
3011    GOTO_OPCODE(ip)                     @ jump to next instruction
3012
3013/* ------------------------------ */
3014    .balign 64
3015.L_OP_SPUT_WIDE: /* 0x68 */
3016/* File: armv5te/OP_SPUT_WIDE.S */
3017    /*
3018     * 64-bit SPUT handler.
3019     */
3020    /* sput-wide vAA, field@BBBB */
3021    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3022    FETCH(r1, 1)                        @ r1<- field ref BBBB
3023    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3024    mov     r9, rINST, lsr #8           @ r9<- AA
3025    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3026    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3027    cmp     r2, #0                      @ is resolved entry null?
3028    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3029.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3030    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3031    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3032    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3033    .if 0
3034    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3035    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3036    .else
3037    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3038    .endif
3039    GOTO_OPCODE(r10)                    @ jump to next instruction
3040
3041/* ------------------------------ */
3042    .balign 64
3043.L_OP_SPUT_OBJECT: /* 0x69 */
3044/* File: armv5te/OP_SPUT_OBJECT.S */
3045    /*
3046     * 32-bit SPUT handler for objects
3047     *
3048     * for: sput-object, sput-object-volatile
3049     */
3050    /* op vAA, field@BBBB */
3051    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3052    FETCH(r1, 1)                        @ r1<- field ref BBBB
3053    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3054    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3055    cmp     r0, #0                      @ is resolved entry null?
3056    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3057    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3058    EXPORT_PC()                         @ resolve() could throw, so export now
3059    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3060    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3061    cmp     r0, #0                      @ success?
3062    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3063    b       common_exceptionThrown      @ no, handle exception
3064
3065
3066/* ------------------------------ */
3067    .balign 64
3068.L_OP_SPUT_BOOLEAN: /* 0x6a */
3069/* File: armv5te/OP_SPUT_BOOLEAN.S */
3070/* File: armv5te/OP_SPUT.S */
3071    /*
3072     * General 32-bit SPUT handler.
3073     *
3074     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3075     */
3076    /* op vAA, field@BBBB */
3077    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3078    FETCH(r1, 1)                        @ r1<- field ref BBBB
3079    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3080    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3081    cmp     r0, #0                      @ is resolved entry null?
3082    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3083.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3084    mov     r2, rINST, lsr #8           @ r2<- AA
3085    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3086    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3088    @ no-op                             @ releasing store
3089    str     r1, [r0, #offStaticField_value] @ field<- vAA
3090    GOTO_OPCODE(ip)                     @ jump to next instruction
3091
3092
3093/* ------------------------------ */
3094    .balign 64
3095.L_OP_SPUT_BYTE: /* 0x6b */
3096/* File: armv5te/OP_SPUT_BYTE.S */
3097/* File: armv5te/OP_SPUT.S */
3098    /*
3099     * General 32-bit SPUT handler.
3100     *
3101     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3102     */
3103    /* op vAA, field@BBBB */
3104    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3105    FETCH(r1, 1)                        @ r1<- field ref BBBB
3106    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3107    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3108    cmp     r0, #0                      @ is resolved entry null?
3109    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3110.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3111    mov     r2, rINST, lsr #8           @ r2<- AA
3112    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3113    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3115    @ no-op                             @ releasing store
3116    str     r1, [r0, #offStaticField_value] @ field<- vAA
3117    GOTO_OPCODE(ip)                     @ jump to next instruction
3118
3119
3120/* ------------------------------ */
3121    .balign 64
3122.L_OP_SPUT_CHAR: /* 0x6c */
3123/* File: armv5te/OP_SPUT_CHAR.S */
3124/* File: armv5te/OP_SPUT.S */
3125    /*
3126     * General 32-bit SPUT handler.
3127     *
3128     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3129     */
3130    /* op vAA, field@BBBB */
3131    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3132    FETCH(r1, 1)                        @ r1<- field ref BBBB
3133    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3134    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3135    cmp     r0, #0                      @ is resolved entry null?
3136    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3137.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3138    mov     r2, rINST, lsr #8           @ r2<- AA
3139    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3140    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3141    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3142    @ no-op                             @ releasing store
3143    str     r1, [r0, #offStaticField_value] @ field<- vAA
3144    GOTO_OPCODE(ip)                     @ jump to next instruction
3145
3146
3147/* ------------------------------ */
3148    .balign 64
3149.L_OP_SPUT_SHORT: /* 0x6d */
3150/* File: armv5te/OP_SPUT_SHORT.S */
3151/* File: armv5te/OP_SPUT.S */
3152    /*
3153     * General 32-bit SPUT handler.
3154     *
3155     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3156     */
3157    /* op vAA, field@BBBB */
3158    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3159    FETCH(r1, 1)                        @ r1<- field ref BBBB
3160    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3161    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3162    cmp     r0, #0                      @ is resolved entry null?
3163    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3164.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3165    mov     r2, rINST, lsr #8           @ r2<- AA
3166    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3167    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3169    @ no-op                             @ releasing store
3170    str     r1, [r0, #offStaticField_value] @ field<- vAA
3171    GOTO_OPCODE(ip)                     @ jump to next instruction
3172
3173
3174/* ------------------------------ */
3175    .balign 64
3176.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3177/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3178    /*
3179     * Handle a virtual method call.
3180     *
3181     * for: invoke-virtual, invoke-virtual/range
3182     */
3183    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3184    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3185    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3186    FETCH(r1, 1)                        @ r1<- BBBB
3187    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3188    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3189    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3190    .if     (!0)
3191    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3192    .endif
3193    cmp     r0, #0                      @ already resolved?
3194    EXPORT_PC()                         @ must export for invoke
3195    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3196    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3197    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3198    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3199    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3200    cmp     r0, #0                      @ got null?
3201    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3202    b       common_exceptionThrown      @ yes, handle exception
3203
3204/* ------------------------------ */
3205    .balign 64
3206.L_OP_INVOKE_SUPER: /* 0x6f */
3207/* File: armv5te/OP_INVOKE_SUPER.S */
3208    /*
3209     * Handle a "super" method call.
3210     *
3211     * for: invoke-super, invoke-super/range
3212     */
3213    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3214    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3215    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3216    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3217    .if     (!0)
3218    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3219    .endif
3220    FETCH(r1, 1)                        @ r1<- BBBB
3221    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3222    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3223    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3224    cmp     r2, #0                      @ null "this"?
3225    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3226    beq     common_errNullObject        @ null "this", throw exception
3227    cmp     r0, #0                      @ already resolved?
3228    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3229    EXPORT_PC()                         @ must export for invoke
3230    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3231    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3232
3233/* ------------------------------ */
3234    .balign 64
3235.L_OP_INVOKE_DIRECT: /* 0x70 */
3236/* File: armv5te/OP_INVOKE_DIRECT.S */
3237    /*
3238     * Handle a direct method call.
3239     *
3240     * (We could defer the "is 'this' pointer null" test to the common
3241     * method invocation code, and use a flag to indicate that static
3242     * calls don't count.  If we do this as part of copying the arguments
3243     * out we could avoiding loading the first arg twice.)
3244     *
3245     * for: invoke-direct, invoke-direct/range
3246     */
3247    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3248    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3249    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3250    FETCH(r1, 1)                        @ r1<- BBBB
3251    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3252    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3253    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3254    .if     (!0)
3255    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3256    .endif
3257    cmp     r0, #0                      @ already resolved?
3258    EXPORT_PC()                         @ must export for invoke
3259    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3260    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3261.LOP_INVOKE_DIRECT_finish:
3262    cmp     r2, #0                      @ null "this" ref?
3263    bne     common_invokeMethodNoRange   @ no, continue on
3264    b       common_errNullObject        @ yes, throw exception
3265
3266/* ------------------------------ */
3267    .balign 64
3268.L_OP_INVOKE_STATIC: /* 0x71 */
3269/* File: armv5te/OP_INVOKE_STATIC.S */
3270    /*
3271     * Handle a static method call.
3272     *
3273     * for: invoke-static, invoke-static/range
3274     */
3275    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3276    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3277    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3278    FETCH(r1, 1)                        @ r1<- BBBB
3279    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3280    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3281    cmp     r0, #0                      @ already resolved?
3282    EXPORT_PC()                         @ must export for invoke
3283    bne     common_invokeMethodNoRange @ yes, continue on
32840:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3285    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3286    mov     r2, #METHOD_STATIC          @ resolver method type
3287    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3288    cmp     r0, #0                      @ got null?
3289    bne     common_invokeMethodNoRange @ no, continue
3290    b       common_exceptionThrown      @ yes, handle exception
3291
3292/* ------------------------------ */
3293    .balign 64
3294.L_OP_INVOKE_INTERFACE: /* 0x72 */
3295/* File: armv5te/OP_INVOKE_INTERFACE.S */
3296    /*
3297     * Handle an interface method call.
3298     *
3299     * for: invoke-interface, invoke-interface/range
3300     */
3301    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3302    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3303    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3304    FETCH(r1, 1)                        @ r1<- BBBB
3305    .if     (!0)
3306    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3307    .endif
3308    EXPORT_PC()                         @ must export for invoke
3309    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3310    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3311    cmp     r0, #0                      @ null obj?
3312    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3313    beq     common_errNullObject        @ yes, fail
3314    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3315    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3316    cmp     r0, #0                      @ failed?
3317    beq     common_exceptionThrown      @ yes, handle exception
3318    b       common_invokeMethodNoRange @ jump to common handler
3319
3320/* ------------------------------ */
3321    .balign 64
3322.L_OP_UNUSED_73: /* 0x73 */
3323/* File: armv5te/OP_UNUSED_73.S */
3324/* File: armv5te/unused.S */
3325    bl      common_abort
3326
3327
3328/* ------------------------------ */
3329    .balign 64
3330.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3331/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3332/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3333    /*
3334     * Handle a virtual method call.
3335     *
3336     * for: invoke-virtual, invoke-virtual/range
3337     */
3338    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3339    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3340    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3341    FETCH(r1, 1)                        @ r1<- BBBB
3342    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3343    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3344    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3345    .if     (!1)
3346    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3347    .endif
3348    cmp     r0, #0                      @ already resolved?
3349    EXPORT_PC()                         @ must export for invoke
3350    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3351    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3352    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3353    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3354    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3355    cmp     r0, #0                      @ got null?
3356    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3357    b       common_exceptionThrown      @ yes, handle exception
3358
3359
3360/* ------------------------------ */
3361    .balign 64
3362.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3363/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3364/* File: armv5te/OP_INVOKE_SUPER.S */
3365    /*
3366     * Handle a "super" method call.
3367     *
3368     * for: invoke-super, invoke-super/range
3369     */
3370    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3371    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3372    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3373    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3374    .if     (!1)
3375    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3376    .endif
3377    FETCH(r1, 1)                        @ r1<- BBBB
3378    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3379    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3380    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3381    cmp     r2, #0                      @ null "this"?
3382    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3383    beq     common_errNullObject        @ null "this", throw exception
3384    cmp     r0, #0                      @ already resolved?
3385    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3386    EXPORT_PC()                         @ must export for invoke
3387    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3388    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3389
3390
3391/* ------------------------------ */
3392    .balign 64
3393.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3394/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3395/* File: armv5te/OP_INVOKE_DIRECT.S */
3396    /*
3397     * Handle a direct method call.
3398     *
3399     * (We could defer the "is 'this' pointer null" test to the common
3400     * method invocation code, and use a flag to indicate that static
3401     * calls don't count.  If we do this as part of copying the arguments
3402     * out we could avoiding loading the first arg twice.)
3403     *
3404     * for: invoke-direct, invoke-direct/range
3405     */
3406    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3407    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3408    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3409    FETCH(r1, 1)                        @ r1<- BBBB
3410    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3411    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3412    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3413    .if     (!1)
3414    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3415    .endif
3416    cmp     r0, #0                      @ already resolved?
3417    EXPORT_PC()                         @ must export for invoke
3418    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3419    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3420.LOP_INVOKE_DIRECT_RANGE_finish:
3421    cmp     r2, #0                      @ null "this" ref?
3422    bne     common_invokeMethodRange   @ no, continue on
3423    b       common_errNullObject        @ yes, throw exception
3424
3425
3426/* ------------------------------ */
3427    .balign 64
3428.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3429/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3430/* File: armv5te/OP_INVOKE_STATIC.S */
3431    /*
3432     * Handle a static method call.
3433     *
3434     * for: invoke-static, invoke-static/range
3435     */
3436    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3437    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3438    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3439    FETCH(r1, 1)                        @ r1<- BBBB
3440    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3441    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3442    cmp     r0, #0                      @ already resolved?
3443    EXPORT_PC()                         @ must export for invoke
3444    bne     common_invokeMethodRange @ yes, continue on
34450:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3446    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3447    mov     r2, #METHOD_STATIC          @ resolver method type
3448    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3449    cmp     r0, #0                      @ got null?
3450    bne     common_invokeMethodRange @ no, continue
3451    b       common_exceptionThrown      @ yes, handle exception
3452
3453
3454/* ------------------------------ */
3455    .balign 64
3456.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3457/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3458/* File: armv5te/OP_INVOKE_INTERFACE.S */
3459    /*
3460     * Handle an interface method call.
3461     *
3462     * for: invoke-interface, invoke-interface/range
3463     */
3464    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3465    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3466    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3467    FETCH(r1, 1)                        @ r1<- BBBB
3468    .if     (!1)
3469    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3470    .endif
3471    EXPORT_PC()                         @ must export for invoke
3472    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3473    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3474    cmp     r0, #0                      @ null obj?
3475    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3476    beq     common_errNullObject        @ yes, fail
3477    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3478    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3479    cmp     r0, #0                      @ failed?
3480    beq     common_exceptionThrown      @ yes, handle exception
3481    b       common_invokeMethodRange @ jump to common handler
3482
3483
3484/* ------------------------------ */
3485    .balign 64
3486.L_OP_UNUSED_79: /* 0x79 */
3487/* File: armv5te/OP_UNUSED_79.S */
3488/* File: armv5te/unused.S */
3489    bl      common_abort
3490
3491
3492/* ------------------------------ */
3493    .balign 64
3494.L_OP_UNUSED_7A: /* 0x7a */
3495/* File: armv5te/OP_UNUSED_7A.S */
3496/* File: armv5te/unused.S */
3497    bl      common_abort
3498
3499
3500/* ------------------------------ */
3501    .balign 64
3502.L_OP_NEG_INT: /* 0x7b */
3503/* File: armv6t2/OP_NEG_INT.S */
3504/* File: armv6t2/unop.S */
3505    /*
3506     * Generic 32-bit unary operation.  Provide an "instr" line that
3507     * specifies an instruction that performs "result = op r0".
3508     * This could be an ARM instruction or a function call.
3509     *
3510     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3511     *      int-to-byte, int-to-char, int-to-short
3512     */
3513    /* unop vA, vB */
3514    mov     r3, rINST, lsr #12          @ r3<- B
3515    ubfx    r9, rINST, #8, #4           @ r9<- A
3516    GET_VREG(r0, r3)                    @ r0<- vB
3517                               @ optional op; may set condition codes
3518    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3519    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3520    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3521    SET_VREG(r0, r9)                    @ vAA<- r0
3522    GOTO_OPCODE(ip)                     @ jump to next instruction
3523    /* 8-9 instructions */
3524
3525
3526/* ------------------------------ */
3527    .balign 64
3528.L_OP_NOT_INT: /* 0x7c */
3529/* File: armv6t2/OP_NOT_INT.S */
3530/* File: armv6t2/unop.S */
3531    /*
3532     * Generic 32-bit unary operation.  Provide an "instr" line that
3533     * specifies an instruction that performs "result = op r0".
3534     * This could be an ARM instruction or a function call.
3535     *
3536     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3537     *      int-to-byte, int-to-char, int-to-short
3538     */
3539    /* unop vA, vB */
3540    mov     r3, rINST, lsr #12          @ r3<- B
3541    ubfx    r9, rINST, #8, #4           @ r9<- A
3542    GET_VREG(r0, r3)                    @ r0<- vB
3543                               @ optional op; may set condition codes
3544    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3545    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3547    SET_VREG(r0, r9)                    @ vAA<- r0
3548    GOTO_OPCODE(ip)                     @ jump to next instruction
3549    /* 8-9 instructions */
3550
3551
3552/* ------------------------------ */
3553    .balign 64
3554.L_OP_NEG_LONG: /* 0x7d */
3555/* File: armv6t2/OP_NEG_LONG.S */
3556/* File: armv6t2/unopWide.S */
3557    /*
3558     * Generic 64-bit unary operation.  Provide an "instr" line that
3559     * specifies an instruction that performs "result = op r0/r1".
3560     * This could be an ARM instruction or a function call.
3561     *
3562     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3563     */
3564    /* unop vA, vB */
3565    mov     r3, rINST, lsr #12          @ r3<- B
3566    ubfx    r9, rINST, #8, #4           @ r9<- A
3567    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3568    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3569    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3570    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3571    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3572    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3574    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3575    GOTO_OPCODE(ip)                     @ jump to next instruction
3576    /* 10-11 instructions */
3577
3578
3579/* ------------------------------ */
3580    .balign 64
3581.L_OP_NOT_LONG: /* 0x7e */
3582/* File: armv6t2/OP_NOT_LONG.S */
3583/* File: armv6t2/unopWide.S */
3584    /*
3585     * Generic 64-bit unary operation.  Provide an "instr" line that
3586     * specifies an instruction that performs "result = op r0/r1".
3587     * This could be an ARM instruction or a function call.
3588     *
3589     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3590     */
3591    /* unop vA, vB */
3592    mov     r3, rINST, lsr #12          @ r3<- B
3593    ubfx    r9, rINST, #8, #4           @ r9<- A
3594    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3595    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3596    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3597    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3598    mvn     r0, r0                           @ optional op; may set condition codes
3599    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3600    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3601    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3602    GOTO_OPCODE(ip)                     @ jump to next instruction
3603    /* 10-11 instructions */
3604
3605
3606/* ------------------------------ */
3607    .balign 64
3608.L_OP_NEG_FLOAT: /* 0x7f */
3609/* File: armv6t2/OP_NEG_FLOAT.S */
3610/* File: armv6t2/unop.S */
3611    /*
3612     * Generic 32-bit unary operation.  Provide an "instr" line that
3613     * specifies an instruction that performs "result = op r0".
3614     * This could be an ARM instruction or a function call.
3615     *
3616     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3617     *      int-to-byte, int-to-char, int-to-short
3618     */
3619    /* unop vA, vB */
3620    mov     r3, rINST, lsr #12          @ r3<- B
3621    ubfx    r9, rINST, #8, #4           @ r9<- A
3622    GET_VREG(r0, r3)                    @ r0<- vB
3623                               @ optional op; may set condition codes
3624    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3625    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3626    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3627    SET_VREG(r0, r9)                    @ vAA<- r0
3628    GOTO_OPCODE(ip)                     @ jump to next instruction
3629    /* 8-9 instructions */
3630
3631
3632/* ------------------------------ */
3633    .balign 64
3634.L_OP_NEG_DOUBLE: /* 0x80 */
3635/* File: armv6t2/OP_NEG_DOUBLE.S */
3636/* File: armv6t2/unopWide.S */
3637    /*
3638     * Generic 64-bit unary operation.  Provide an "instr" line that
3639     * specifies an instruction that performs "result = op r0/r1".
3640     * This could be an ARM instruction or a function call.
3641     *
3642     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3643     */
3644    /* unop vA, vB */
3645    mov     r3, rINST, lsr #12          @ r3<- B
3646    ubfx    r9, rINST, #8, #4           @ r9<- A
3647    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3648    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3649    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3650    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3651                               @ optional op; may set condition codes
3652    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3654    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3655    GOTO_OPCODE(ip)                     @ jump to next instruction
3656    /* 10-11 instructions */
3657
3658
3659/* ------------------------------ */
3660    .balign 64
3661.L_OP_INT_TO_LONG: /* 0x81 */
3662/* File: armv6t2/OP_INT_TO_LONG.S */
3663/* File: armv6t2/unopWider.S */
3664    /*
3665     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3666     * that specifies an instruction that performs "result = op r0", where
3667     * "result" is a 64-bit quantity in r0/r1.
3668     *
3669     * For: int-to-long, int-to-double, float-to-long, float-to-double
3670     */
3671    /* unop vA, vB */
3672    mov     r3, rINST, lsr #12          @ r3<- B
3673    ubfx    r9, rINST, #8, #4           @ r9<- A
3674    GET_VREG(r0, r3)                    @ r0<- vB
3675    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3676                               @ optional op; may set condition codes
3677    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3678    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3679    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3680    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3681    GOTO_OPCODE(ip)                     @ jump to next instruction
3682    /* 9-10 instructions */
3683
3684
3685/* ------------------------------ */
3686    .balign 64
3687.L_OP_INT_TO_FLOAT: /* 0x82 */
3688/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3689/* File: arm-vfp/funop.S */
3690    /*
3691     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3692     * line that specifies an instruction that performs "s1 = op s0".
3693     *
3694     * for: int-to-float, float-to-int
3695     */
3696    /* unop vA, vB */
3697    mov     r3, rINST, lsr #12          @ r3<- B
3698    mov     r9, rINST, lsr #8           @ r9<- A+
3699    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3700    flds    s0, [r3]                    @ s0<- vB
3701    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3702    and     r9, r9, #15                 @ r9<- A
3703    fsitos  s1, s0                              @ s1<- op
3704    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3705    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3706    fsts    s1, [r9]                    @ vA<- s1
3707    GOTO_OPCODE(ip)                     @ jump to next instruction
3708
3709
3710/* ------------------------------ */
3711    .balign 64
3712.L_OP_INT_TO_DOUBLE: /* 0x83 */
3713/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3714/* File: arm-vfp/funopWider.S */
3715    /*
3716     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3717     * "instr" line that specifies an instruction that performs "d0 = op s0".
3718     *
3719     * For: int-to-double, float-to-double
3720     */
3721    /* unop vA, vB */
3722    mov     r3, rINST, lsr #12          @ r3<- B
3723    mov     r9, rINST, lsr #8           @ r9<- A+
3724    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3725    flds    s0, [r3]                    @ s0<- vB
3726    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3727    and     r9, r9, #15                 @ r9<- A
3728    fsitod  d0, s0                              @ d0<- op
3729    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3730    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3731    fstd    d0, [r9]                    @ vA<- d0
3732    GOTO_OPCODE(ip)                     @ jump to next instruction
3733
3734
3735/* ------------------------------ */
3736    .balign 64
3737.L_OP_LONG_TO_INT: /* 0x84 */
3738/* File: armv5te/OP_LONG_TO_INT.S */
3739/* we ignore the high word, making this equivalent to a 32-bit reg move */
3740/* File: armv5te/OP_MOVE.S */
3741    /* for move, move-object, long-to-int */
3742    /* op vA, vB */
3743    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3744    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3745    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3746    GET_VREG(r2, r1)                    @ r2<- fp[B]
3747    and     r0, r0, #15
3748    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3749    SET_VREG(r2, r0)                    @ fp[A]<- r2
3750    GOTO_OPCODE(ip)                     @ execute next instruction
3751
3752
3753/* ------------------------------ */
3754    .balign 64
3755.L_OP_LONG_TO_FLOAT: /* 0x85 */
3756/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3757/* File: armv6t2/unopNarrower.S */
3758    /*
3759     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3760     * that specifies an instruction that performs "result = op r0/r1", where
3761     * "result" is a 32-bit quantity in r0.
3762     *
3763     * For: long-to-float, double-to-int, double-to-float
3764     *
3765     * (This would work for long-to-int, but that instruction is actually
3766     * an exact match for OP_MOVE.)
3767     */
3768    /* unop vA, vB */
3769    mov     r3, rINST, lsr #12          @ r3<- B
3770    ubfx    r9, rINST, #8, #4           @ r9<- A
3771    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3772    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3773    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3774                               @ optional op; may set condition codes
3775    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3777    SET_VREG(r0, r9)                    @ vA<- r0
3778    GOTO_OPCODE(ip)                     @ jump to next instruction
3779    /* 9-10 instructions */
3780
3781
3782/* ------------------------------ */
3783    .balign 64
3784.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3785/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3786/* File: armv6t2/unopWide.S */
3787    /*
3788     * Generic 64-bit unary operation.  Provide an "instr" line that
3789     * specifies an instruction that performs "result = op r0/r1".
3790     * This could be an ARM instruction or a function call.
3791     *
3792     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3793     */
3794    /* unop vA, vB */
3795    mov     r3, rINST, lsr #12          @ r3<- B
3796    ubfx    r9, rINST, #8, #4           @ r9<- A
3797    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3798    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3799    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3800    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3801                               @ optional op; may set condition codes
3802    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3803    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3804    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3805    GOTO_OPCODE(ip)                     @ jump to next instruction
3806    /* 10-11 instructions */
3807
3808
3809/* ------------------------------ */
3810    .balign 64
3811.L_OP_FLOAT_TO_INT: /* 0x87 */
3812/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3813/* File: arm-vfp/funop.S */
3814    /*
3815     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3816     * line that specifies an instruction that performs "s1 = op s0".
3817     *
3818     * for: int-to-float, float-to-int
3819     */
3820    /* unop vA, vB */
3821    mov     r3, rINST, lsr #12          @ r3<- B
3822    mov     r9, rINST, lsr #8           @ r9<- A+
3823    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3824    flds    s0, [r3]                    @ s0<- vB
3825    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3826    and     r9, r9, #15                 @ r9<- A
3827    ftosizs s1, s0                              @ s1<- op
3828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3829    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3830    fsts    s1, [r9]                    @ vA<- s1
3831    GOTO_OPCODE(ip)                     @ jump to next instruction
3832
3833
3834/* ------------------------------ */
3835    .balign 64
3836.L_OP_FLOAT_TO_LONG: /* 0x88 */
3837/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3838@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3839/* File: armv6t2/unopWider.S */
3840    /*
3841     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3842     * that specifies an instruction that performs "result = op r0", where
3843     * "result" is a 64-bit quantity in r0/r1.
3844     *
3845     * For: int-to-long, int-to-double, float-to-long, float-to-double
3846     */
3847    /* unop vA, vB */
3848    mov     r3, rINST, lsr #12          @ r3<- B
3849    ubfx    r9, rINST, #8, #4           @ r9<- A
3850    GET_VREG(r0, r3)                    @ r0<- vB
3851    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3852                               @ optional op; may set condition codes
3853    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3854    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3856    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3857    GOTO_OPCODE(ip)                     @ jump to next instruction
3858    /* 9-10 instructions */
3859
3860
3861
3862/* ------------------------------ */
3863    .balign 64
3864.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3865/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3866/* File: arm-vfp/funopWider.S */
3867    /*
3868     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3869     * "instr" line that specifies an instruction that performs "d0 = op s0".
3870     *
3871     * For: int-to-double, float-to-double
3872     */
3873    /* unop vA, vB */
3874    mov     r3, rINST, lsr #12          @ r3<- B
3875    mov     r9, rINST, lsr #8           @ r9<- A+
3876    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3877    flds    s0, [r3]                    @ s0<- vB
3878    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3879    and     r9, r9, #15                 @ r9<- A
3880    fcvtds  d0, s0                              @ d0<- op
3881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3882    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3883    fstd    d0, [r9]                    @ vA<- d0
3884    GOTO_OPCODE(ip)                     @ jump to next instruction
3885
3886
3887/* ------------------------------ */
3888    .balign 64
3889.L_OP_DOUBLE_TO_INT: /* 0x8a */
3890/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3891/* File: arm-vfp/funopNarrower.S */
3892    /*
3893     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3894     * "instr" line that specifies an instruction that performs "s0 = op d0".
3895     *
3896     * For: double-to-int, double-to-float
3897     */
3898    /* unop vA, vB */
3899    mov     r3, rINST, lsr #12          @ r3<- B
3900    mov     r9, rINST, lsr #8           @ r9<- A+
3901    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3902    fldd    d0, [r3]                    @ d0<- vB
3903    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3904    and     r9, r9, #15                 @ r9<- A
3905    ftosizd  s0, d0                              @ s0<- op
3906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3907    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3908    fsts    s0, [r9]                    @ vA<- s0
3909    GOTO_OPCODE(ip)                     @ jump to next instruction
3910
3911
3912/* ------------------------------ */
3913    .balign 64
3914.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3915/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3916@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3917/* File: armv6t2/unopWide.S */
3918    /*
3919     * Generic 64-bit unary operation.  Provide an "instr" line that
3920     * specifies an instruction that performs "result = op r0/r1".
3921     * This could be an ARM instruction or a function call.
3922     *
3923     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3924     */
3925    /* unop vA, vB */
3926    mov     r3, rINST, lsr #12          @ r3<- B
3927    ubfx    r9, rINST, #8, #4           @ r9<- A
3928    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3929    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3930    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3931    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3932                               @ optional op; may set condition codes
3933    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3934    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3935    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3936    GOTO_OPCODE(ip)                     @ jump to next instruction
3937    /* 10-11 instructions */
3938
3939
3940
3941/* ------------------------------ */
3942    .balign 64
3943.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3944/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3945/* File: arm-vfp/funopNarrower.S */
3946    /*
3947     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3948     * "instr" line that specifies an instruction that performs "s0 = op d0".
3949     *
3950     * For: double-to-int, double-to-float
3951     */
3952    /* unop vA, vB */
3953    mov     r3, rINST, lsr #12          @ r3<- B
3954    mov     r9, rINST, lsr #8           @ r9<- A+
3955    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3956    fldd    d0, [r3]                    @ d0<- vB
3957    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3958    and     r9, r9, #15                 @ r9<- A
3959    fcvtsd  s0, d0                              @ s0<- op
3960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3961    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3962    fsts    s0, [r9]                    @ vA<- s0
3963    GOTO_OPCODE(ip)                     @ jump to next instruction
3964
3965
3966/* ------------------------------ */
3967    .balign 64
3968.L_OP_INT_TO_BYTE: /* 0x8d */
3969/* File: armv6t2/OP_INT_TO_BYTE.S */
3970/* File: armv6t2/unop.S */
3971    /*
3972     * Generic 32-bit unary operation.  Provide an "instr" line that
3973     * specifies an instruction that performs "result = op r0".
3974     * This could be an ARM instruction or a function call.
3975     *
3976     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3977     *      int-to-byte, int-to-char, int-to-short
3978     */
3979    /* unop vA, vB */
3980    mov     r3, rINST, lsr #12          @ r3<- B
3981    ubfx    r9, rINST, #8, #4           @ r9<- A
3982    GET_VREG(r0, r3)                    @ r0<- vB
3983                               @ optional op; may set condition codes
3984    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3985    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3987    SET_VREG(r0, r9)                    @ vAA<- r0
3988    GOTO_OPCODE(ip)                     @ jump to next instruction
3989    /* 8-9 instructions */
3990
3991
3992/* ------------------------------ */
3993    .balign 64
3994.L_OP_INT_TO_CHAR: /* 0x8e */
3995/* File: armv6t2/OP_INT_TO_CHAR.S */
3996/* File: armv6t2/unop.S */
3997    /*
3998     * Generic 32-bit unary operation.  Provide an "instr" line that
3999     * specifies an instruction that performs "result = op r0".
4000     * This could be an ARM instruction or a function call.
4001     *
4002     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4003     *      int-to-byte, int-to-char, int-to-short
4004     */
4005    /* unop vA, vB */
4006    mov     r3, rINST, lsr #12          @ r3<- B
4007    ubfx    r9, rINST, #8, #4           @ r9<- A
4008    GET_VREG(r0, r3)                    @ r0<- vB
4009                               @ optional op; may set condition codes
4010    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4011    uxth    r0, r0                              @ r0<- op, r0-r3 changed
4012    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4013    SET_VREG(r0, r9)                    @ vAA<- r0
4014    GOTO_OPCODE(ip)                     @ jump to next instruction
4015    /* 8-9 instructions */
4016
4017
4018/* ------------------------------ */
4019    .balign 64
4020.L_OP_INT_TO_SHORT: /* 0x8f */
4021/* File: armv6t2/OP_INT_TO_SHORT.S */
4022/* File: armv6t2/unop.S */
4023    /*
4024     * Generic 32-bit unary operation.  Provide an "instr" line that
4025     * specifies an instruction that performs "result = op r0".
4026     * This could be an ARM instruction or a function call.
4027     *
4028     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4029     *      int-to-byte, int-to-char, int-to-short
4030     */
4031    /* unop vA, vB */
4032    mov     r3, rINST, lsr #12          @ r3<- B
4033    ubfx    r9, rINST, #8, #4           @ r9<- A
4034    GET_VREG(r0, r3)                    @ r0<- vB
4035                               @ optional op; may set condition codes
4036    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4037    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4038    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4039    SET_VREG(r0, r9)                    @ vAA<- r0
4040    GOTO_OPCODE(ip)                     @ jump to next instruction
4041    /* 8-9 instructions */
4042
4043
4044/* ------------------------------ */
4045    .balign 64
4046.L_OP_ADD_INT: /* 0x90 */
4047/* File: armv5te/OP_ADD_INT.S */
4048/* File: armv5te/binop.S */
4049    /*
4050     * Generic 32-bit binary operation.  Provide an "instr" line that
4051     * specifies an instruction that performs "result = r0 op r1".
4052     * This could be an ARM instruction or a function call.  (If the result
4053     * comes back in a register other than r0, you can override "result".)
4054     *
4055     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4056     * vCC (r1).  Useful for integer division and modulus.  Note that we
4057     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4058     * handles it correctly.
4059     *
4060     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4061     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4062     *      mul-float, div-float, rem-float
4063     */
4064    /* binop vAA, vBB, vCC */
4065    FETCH(r0, 1)                        @ r0<- CCBB
4066    mov     r9, rINST, lsr #8           @ r9<- AA
4067    mov     r3, r0, lsr #8              @ r3<- CC
4068    and     r2, r0, #255                @ r2<- BB
4069    GET_VREG(r1, r3)                    @ r1<- vCC
4070    GET_VREG(r0, r2)                    @ r0<- vBB
4071    .if 0
4072    cmp     r1, #0                      @ is second operand zero?
4073    beq     common_errDivideByZero
4074    .endif
4075
4076    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4077                               @ optional op; may set condition codes
4078    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4079    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4080    SET_VREG(r0, r9)               @ vAA<- r0
4081    GOTO_OPCODE(ip)                     @ jump to next instruction
4082    /* 11-14 instructions */
4083
4084
4085/* ------------------------------ */
4086    .balign 64
4087.L_OP_SUB_INT: /* 0x91 */
4088/* File: armv5te/OP_SUB_INT.S */
4089/* File: armv5te/binop.S */
4090    /*
4091     * Generic 32-bit binary operation.  Provide an "instr" line that
4092     * specifies an instruction that performs "result = r0 op r1".
4093     * This could be an ARM instruction or a function call.  (If the result
4094     * comes back in a register other than r0, you can override "result".)
4095     *
4096     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4097     * vCC (r1).  Useful for integer division and modulus.  Note that we
4098     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4099     * handles it correctly.
4100     *
4101     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4102     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4103     *      mul-float, div-float, rem-float
4104     */
4105    /* binop vAA, vBB, vCC */
4106    FETCH(r0, 1)                        @ r0<- CCBB
4107    mov     r9, rINST, lsr #8           @ r9<- AA
4108    mov     r3, r0, lsr #8              @ r3<- CC
4109    and     r2, r0, #255                @ r2<- BB
4110    GET_VREG(r1, r3)                    @ r1<- vCC
4111    GET_VREG(r0, r2)                    @ r0<- vBB
4112    .if 0
4113    cmp     r1, #0                      @ is second operand zero?
4114    beq     common_errDivideByZero
4115    .endif
4116
4117    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4118                               @ optional op; may set condition codes
4119    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4120    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4121    SET_VREG(r0, r9)               @ vAA<- r0
4122    GOTO_OPCODE(ip)                     @ jump to next instruction
4123    /* 11-14 instructions */
4124
4125
4126/* ------------------------------ */
4127    .balign 64
4128.L_OP_MUL_INT: /* 0x92 */
4129/* File: armv5te/OP_MUL_INT.S */
4130/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4131/* File: armv5te/binop.S */
4132    /*
4133     * Generic 32-bit binary operation.  Provide an "instr" line that
4134     * specifies an instruction that performs "result = r0 op r1".
4135     * This could be an ARM instruction or a function call.  (If the result
4136     * comes back in a register other than r0, you can override "result".)
4137     *
4138     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4139     * vCC (r1).  Useful for integer division and modulus.  Note that we
4140     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4141     * handles it correctly.
4142     *
4143     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4144     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4145     *      mul-float, div-float, rem-float
4146     */
4147    /* binop vAA, vBB, vCC */
4148    FETCH(r0, 1)                        @ r0<- CCBB
4149    mov     r9, rINST, lsr #8           @ r9<- AA
4150    mov     r3, r0, lsr #8              @ r3<- CC
4151    and     r2, r0, #255                @ r2<- BB
4152    GET_VREG(r1, r3)                    @ r1<- vCC
4153    GET_VREG(r0, r2)                    @ r0<- vBB
4154    .if 0
4155    cmp     r1, #0                      @ is second operand zero?
4156    beq     common_errDivideByZero
4157    .endif
4158
4159    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4160                               @ optional op; may set condition codes
4161    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4162    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4163    SET_VREG(r0, r9)               @ vAA<- r0
4164    GOTO_OPCODE(ip)                     @ jump to next instruction
4165    /* 11-14 instructions */
4166
4167
4168/* ------------------------------ */
4169    .balign 64
4170.L_OP_DIV_INT: /* 0x93 */
4171/* File: armv5te/OP_DIV_INT.S */
4172/* File: armv5te/binop.S */
4173    /*
4174     * Generic 32-bit binary operation.  Provide an "instr" line that
4175     * specifies an instruction that performs "result = r0 op r1".
4176     * This could be an ARM instruction or a function call.  (If the result
4177     * comes back in a register other than r0, you can override "result".)
4178     *
4179     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4180     * vCC (r1).  Useful for integer division and modulus.  Note that we
4181     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4182     * handles it correctly.
4183     *
4184     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4185     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4186     *      mul-float, div-float, rem-float
4187     */
4188    /* binop vAA, vBB, vCC */
4189    FETCH(r0, 1)                        @ r0<- CCBB
4190    mov     r9, rINST, lsr #8           @ r9<- AA
4191    mov     r3, r0, lsr #8              @ r3<- CC
4192    and     r2, r0, #255                @ r2<- BB
4193    GET_VREG(r1, r3)                    @ r1<- vCC
4194    GET_VREG(r0, r2)                    @ r0<- vBB
4195    .if 1
4196    cmp     r1, #0                      @ is second operand zero?
4197    beq     common_errDivideByZero
4198    .endif
4199
4200    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4201                               @ optional op; may set condition codes
4202    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4203    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4204    SET_VREG(r0, r9)               @ vAA<- r0
4205    GOTO_OPCODE(ip)                     @ jump to next instruction
4206    /* 11-14 instructions */
4207
4208
4209/* ------------------------------ */
4210    .balign 64
4211.L_OP_REM_INT: /* 0x94 */
4212/* File: armv5te/OP_REM_INT.S */
4213/* idivmod returns quotient in r0 and remainder in r1 */
4214/* File: armv5te/binop.S */
4215    /*
4216     * Generic 32-bit binary operation.  Provide an "instr" line that
4217     * specifies an instruction that performs "result = r0 op r1".
4218     * This could be an ARM instruction or a function call.  (If the result
4219     * comes back in a register other than r0, you can override "result".)
4220     *
4221     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4222     * vCC (r1).  Useful for integer division and modulus.  Note that we
4223     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4224     * handles it correctly.
4225     *
4226     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4227     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4228     *      mul-float, div-float, rem-float
4229     */
4230    /* binop vAA, vBB, vCC */
4231    FETCH(r0, 1)                        @ r0<- CCBB
4232    mov     r9, rINST, lsr #8           @ r9<- AA
4233    mov     r3, r0, lsr #8              @ r3<- CC
4234    and     r2, r0, #255                @ r2<- BB
4235    GET_VREG(r1, r3)                    @ r1<- vCC
4236    GET_VREG(r0, r2)                    @ r0<- vBB
4237    .if 1
4238    cmp     r1, #0                      @ is second operand zero?
4239    beq     common_errDivideByZero
4240    .endif
4241
4242    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4243                               @ optional op; may set condition codes
4244    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4246    SET_VREG(r1, r9)               @ vAA<- r1
4247    GOTO_OPCODE(ip)                     @ jump to next instruction
4248    /* 11-14 instructions */
4249
4250
4251/* ------------------------------ */
4252    .balign 64
4253.L_OP_AND_INT: /* 0x95 */
4254/* File: armv5te/OP_AND_INT.S */
4255/* File: armv5te/binop.S */
4256    /*
4257     * Generic 32-bit binary operation.  Provide an "instr" line that
4258     * specifies an instruction that performs "result = r0 op r1".
4259     * This could be an ARM instruction or a function call.  (If the result
4260     * comes back in a register other than r0, you can override "result".)
4261     *
4262     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4263     * vCC (r1).  Useful for integer division and modulus.  Note that we
4264     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4265     * handles it correctly.
4266     *
4267     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4268     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4269     *      mul-float, div-float, rem-float
4270     */
4271    /* binop vAA, vBB, vCC */
4272    FETCH(r0, 1)                        @ r0<- CCBB
4273    mov     r9, rINST, lsr #8           @ r9<- AA
4274    mov     r3, r0, lsr #8              @ r3<- CC
4275    and     r2, r0, #255                @ r2<- BB
4276    GET_VREG(r1, r3)                    @ r1<- vCC
4277    GET_VREG(r0, r2)                    @ r0<- vBB
4278    .if 0
4279    cmp     r1, #0                      @ is second operand zero?
4280    beq     common_errDivideByZero
4281    .endif
4282
4283    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4284                               @ optional op; may set condition codes
4285    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4286    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4287    SET_VREG(r0, r9)               @ vAA<- r0
4288    GOTO_OPCODE(ip)                     @ jump to next instruction
4289    /* 11-14 instructions */
4290
4291
4292/* ------------------------------ */
4293    .balign 64
4294.L_OP_OR_INT: /* 0x96 */
4295/* File: armv5te/OP_OR_INT.S */
4296/* File: armv5te/binop.S */
4297    /*
4298     * Generic 32-bit binary operation.  Provide an "instr" line that
4299     * specifies an instruction that performs "result = r0 op r1".
4300     * This could be an ARM instruction or a function call.  (If the result
4301     * comes back in a register other than r0, you can override "result".)
4302     *
4303     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4304     * vCC (r1).  Useful for integer division and modulus.  Note that we
4305     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4306     * handles it correctly.
4307     *
4308     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4309     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4310     *      mul-float, div-float, rem-float
4311     */
4312    /* binop vAA, vBB, vCC */
4313    FETCH(r0, 1)                        @ r0<- CCBB
4314    mov     r9, rINST, lsr #8           @ r9<- AA
4315    mov     r3, r0, lsr #8              @ r3<- CC
4316    and     r2, r0, #255                @ r2<- BB
4317    GET_VREG(r1, r3)                    @ r1<- vCC
4318    GET_VREG(r0, r2)                    @ r0<- vBB
4319    .if 0
4320    cmp     r1, #0                      @ is second operand zero?
4321    beq     common_errDivideByZero
4322    .endif
4323
4324    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4325                               @ optional op; may set condition codes
4326    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4328    SET_VREG(r0, r9)               @ vAA<- r0
4329    GOTO_OPCODE(ip)                     @ jump to next instruction
4330    /* 11-14 instructions */
4331
4332
4333/* ------------------------------ */
4334    .balign 64
4335.L_OP_XOR_INT: /* 0x97 */
4336/* File: armv5te/OP_XOR_INT.S */
4337/* File: armv5te/binop.S */
4338    /*
4339     * Generic 32-bit binary operation.  Provide an "instr" line that
4340     * specifies an instruction that performs "result = r0 op r1".
4341     * This could be an ARM instruction or a function call.  (If the result
4342     * comes back in a register other than r0, you can override "result".)
4343     *
4344     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4345     * vCC (r1).  Useful for integer division and modulus.  Note that we
4346     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4347     * handles it correctly.
4348     *
4349     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4350     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4351     *      mul-float, div-float, rem-float
4352     */
4353    /* binop vAA, vBB, vCC */
4354    FETCH(r0, 1)                        @ r0<- CCBB
4355    mov     r9, rINST, lsr #8           @ r9<- AA
4356    mov     r3, r0, lsr #8              @ r3<- CC
4357    and     r2, r0, #255                @ r2<- BB
4358    GET_VREG(r1, r3)                    @ r1<- vCC
4359    GET_VREG(r0, r2)                    @ r0<- vBB
4360    .if 0
4361    cmp     r1, #0                      @ is second operand zero?
4362    beq     common_errDivideByZero
4363    .endif
4364
4365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4366                               @ optional op; may set condition codes
4367    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4369    SET_VREG(r0, r9)               @ vAA<- r0
4370    GOTO_OPCODE(ip)                     @ jump to next instruction
4371    /* 11-14 instructions */
4372
4373
4374/* ------------------------------ */
4375    .balign 64
4376.L_OP_SHL_INT: /* 0x98 */
4377/* File: armv5te/OP_SHL_INT.S */
4378/* File: armv5te/binop.S */
4379    /*
4380     * Generic 32-bit binary operation.  Provide an "instr" line that
4381     * specifies an instruction that performs "result = r0 op r1".
4382     * This could be an ARM instruction or a function call.  (If the result
4383     * comes back in a register other than r0, you can override "result".)
4384     *
4385     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4386     * vCC (r1).  Useful for integer division and modulus.  Note that we
4387     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4388     * handles it correctly.
4389     *
4390     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4391     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4392     *      mul-float, div-float, rem-float
4393     */
4394    /* binop vAA, vBB, vCC */
4395    FETCH(r0, 1)                        @ r0<- CCBB
4396    mov     r9, rINST, lsr #8           @ r9<- AA
4397    mov     r3, r0, lsr #8              @ r3<- CC
4398    and     r2, r0, #255                @ r2<- BB
4399    GET_VREG(r1, r3)                    @ r1<- vCC
4400    GET_VREG(r0, r2)                    @ r0<- vBB
4401    .if 0
4402    cmp     r1, #0                      @ is second operand zero?
4403    beq     common_errDivideByZero
4404    .endif
4405
4406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4407    and     r1, r1, #31                           @ optional op; may set condition codes
4408    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4409    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4410    SET_VREG(r0, r9)               @ vAA<- r0
4411    GOTO_OPCODE(ip)                     @ jump to next instruction
4412    /* 11-14 instructions */
4413
4414
4415/* ------------------------------ */
4416    .balign 64
4417.L_OP_SHR_INT: /* 0x99 */
4418/* File: armv5te/OP_SHR_INT.S */
4419/* File: armv5te/binop.S */
4420    /*
4421     * Generic 32-bit binary operation.  Provide an "instr" line that
4422     * specifies an instruction that performs "result = r0 op r1".
4423     * This could be an ARM instruction or a function call.  (If the result
4424     * comes back in a register other than r0, you can override "result".)
4425     *
4426     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4427     * vCC (r1).  Useful for integer division and modulus.  Note that we
4428     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4429     * handles it correctly.
4430     *
4431     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4432     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4433     *      mul-float, div-float, rem-float
4434     */
4435    /* binop vAA, vBB, vCC */
4436    FETCH(r0, 1)                        @ r0<- CCBB
4437    mov     r9, rINST, lsr #8           @ r9<- AA
4438    mov     r3, r0, lsr #8              @ r3<- CC
4439    and     r2, r0, #255                @ r2<- BB
4440    GET_VREG(r1, r3)                    @ r1<- vCC
4441    GET_VREG(r0, r2)                    @ r0<- vBB
4442    .if 0
4443    cmp     r1, #0                      @ is second operand zero?
4444    beq     common_errDivideByZero
4445    .endif
4446
4447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4448    and     r1, r1, #31                           @ optional op; may set condition codes
4449    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4450    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4451    SET_VREG(r0, r9)               @ vAA<- r0
4452    GOTO_OPCODE(ip)                     @ jump to next instruction
4453    /* 11-14 instructions */
4454
4455
4456/* ------------------------------ */
4457    .balign 64
4458.L_OP_USHR_INT: /* 0x9a */
4459/* File: armv5te/OP_USHR_INT.S */
4460/* File: armv5te/binop.S */
4461    /*
4462     * Generic 32-bit binary operation.  Provide an "instr" line that
4463     * specifies an instruction that performs "result = r0 op r1".
4464     * This could be an ARM instruction or a function call.  (If the result
4465     * comes back in a register other than r0, you can override "result".)
4466     *
4467     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4468     * vCC (r1).  Useful for integer division and modulus.  Note that we
4469     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4470     * handles it correctly.
4471     *
4472     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4473     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4474     *      mul-float, div-float, rem-float
4475     */
4476    /* binop vAA, vBB, vCC */
4477    FETCH(r0, 1)                        @ r0<- CCBB
4478    mov     r9, rINST, lsr #8           @ r9<- AA
4479    mov     r3, r0, lsr #8              @ r3<- CC
4480    and     r2, r0, #255                @ r2<- BB
4481    GET_VREG(r1, r3)                    @ r1<- vCC
4482    GET_VREG(r0, r2)                    @ r0<- vBB
4483    .if 0
4484    cmp     r1, #0                      @ is second operand zero?
4485    beq     common_errDivideByZero
4486    .endif
4487
4488    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4489    and     r1, r1, #31                           @ optional op; may set condition codes
4490    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4492    SET_VREG(r0, r9)               @ vAA<- r0
4493    GOTO_OPCODE(ip)                     @ jump to next instruction
4494    /* 11-14 instructions */
4495
4496
4497/* ------------------------------ */
4498    .balign 64
4499.L_OP_ADD_LONG: /* 0x9b */
4500/* File: armv5te/OP_ADD_LONG.S */
4501/* File: armv5te/binopWide.S */
4502    /*
4503     * Generic 64-bit binary operation.  Provide an "instr" line that
4504     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4505     * This could be an ARM instruction or a function call.  (If the result
4506     * comes back in a register other than r0, you can override "result".)
4507     *
4508     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4509     * vCC (r1).  Useful for integer division and modulus.
4510     *
4511     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4512     *      xor-long, add-double, sub-double, mul-double, div-double,
4513     *      rem-double
4514     *
4515     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4516     */
4517    /* binop vAA, vBB, vCC */
4518    FETCH(r0, 1)                        @ r0<- CCBB
4519    mov     r9, rINST, lsr #8           @ r9<- AA
4520    and     r2, r0, #255                @ r2<- BB
4521    mov     r3, r0, lsr #8              @ r3<- CC
4522    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4523    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4524    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4525    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4526    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4527    .if 0
4528    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4529    beq     common_errDivideByZero
4530    .endif
4531    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4532
4533    adds    r0, r0, r2                           @ optional op; may set condition codes
4534    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4536    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4537    GOTO_OPCODE(ip)                     @ jump to next instruction
4538    /* 14-17 instructions */
4539
4540
4541/* ------------------------------ */
4542    .balign 64
4543.L_OP_SUB_LONG: /* 0x9c */
4544/* File: armv5te/OP_SUB_LONG.S */
4545/* File: armv5te/binopWide.S */
4546    /*
4547     * Generic 64-bit binary operation.  Provide an "instr" line that
4548     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4549     * This could be an ARM instruction or a function call.  (If the result
4550     * comes back in a register other than r0, you can override "result".)
4551     *
4552     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4553     * vCC (r1).  Useful for integer division and modulus.
4554     *
4555     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4556     *      xor-long, add-double, sub-double, mul-double, div-double,
4557     *      rem-double
4558     *
4559     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4560     */
4561    /* binop vAA, vBB, vCC */
4562    FETCH(r0, 1)                        @ r0<- CCBB
4563    mov     r9, rINST, lsr #8           @ r9<- AA
4564    and     r2, r0, #255                @ r2<- BB
4565    mov     r3, r0, lsr #8              @ r3<- CC
4566    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4567    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4568    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4569    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4570    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4571    .if 0
4572    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4573    beq     common_errDivideByZero
4574    .endif
4575    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4576
4577    subs    r0, r0, r2                           @ optional op; may set condition codes
4578    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4580    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4581    GOTO_OPCODE(ip)                     @ jump to next instruction
4582    /* 14-17 instructions */
4583
4584
4585/* ------------------------------ */
4586    .balign 64
4587.L_OP_MUL_LONG: /* 0x9d */
4588/* File: armv5te/OP_MUL_LONG.S */
4589    /*
4590     * Signed 64-bit integer multiply.
4591     *
4592     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4593     *        WX
4594     *      x YZ
4595     *  --------
4596     *     ZW ZX
4597     *  YW YX
4598     *
4599     * The low word of the result holds ZX, the high word holds
4600     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4601     * it doesn't fit in the low 64 bits.
4602     *
4603     * Unlike most ARM math operations, multiply instructions have
4604     * restrictions on using the same register more than once (Rd and Rm
4605     * cannot be the same).
4606     */
4607    /* mul-long vAA, vBB, vCC */
4608    FETCH(r0, 1)                        @ r0<- CCBB
4609    and     r2, r0, #255                @ r2<- BB
4610    mov     r3, r0, lsr #8              @ r3<- CC
4611    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4612    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4613    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4614    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4615    mul     ip, r2, r1                  @  ip<- ZxW
4616    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4617    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4618    mov     r0, rINST, lsr #8           @ r0<- AA
4619    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4620    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4621    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4622    b       .LOP_MUL_LONG_finish
4623
4624/* ------------------------------ */
4625    .balign 64
4626.L_OP_DIV_LONG: /* 0x9e */
4627/* File: armv5te/OP_DIV_LONG.S */
4628/* File: armv5te/binopWide.S */
4629    /*
4630     * Generic 64-bit binary operation.  Provide an "instr" line that
4631     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4632     * This could be an ARM instruction or a function call.  (If the result
4633     * comes back in a register other than r0, you can override "result".)
4634     *
4635     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4636     * vCC (r1).  Useful for integer division and modulus.
4637     *
4638     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4639     *      xor-long, add-double, sub-double, mul-double, div-double,
4640     *      rem-double
4641     *
4642     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4643     */
4644    /* binop vAA, vBB, vCC */
4645    FETCH(r0, 1)                        @ r0<- CCBB
4646    mov     r9, rINST, lsr #8           @ r9<- AA
4647    and     r2, r0, #255                @ r2<- BB
4648    mov     r3, r0, lsr #8              @ r3<- CC
4649    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4650    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4651    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4652    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4653    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4654    .if 1
4655    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4656    beq     common_errDivideByZero
4657    .endif
4658    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4659
4660                               @ optional op; may set condition codes
4661    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4662    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4663    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4664    GOTO_OPCODE(ip)                     @ jump to next instruction
4665    /* 14-17 instructions */
4666
4667
4668/* ------------------------------ */
4669    .balign 64
4670.L_OP_REM_LONG: /* 0x9f */
4671/* File: armv5te/OP_REM_LONG.S */
4672/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4673/* File: armv5te/binopWide.S */
4674    /*
4675     * Generic 64-bit binary operation.  Provide an "instr" line that
4676     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4677     * This could be an ARM instruction or a function call.  (If the result
4678     * comes back in a register other than r0, you can override "result".)
4679     *
4680     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4681     * vCC (r1).  Useful for integer division and modulus.
4682     *
4683     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4684     *      xor-long, add-double, sub-double, mul-double, div-double,
4685     *      rem-double
4686     *
4687     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4688     */
4689    /* binop vAA, vBB, vCC */
4690    FETCH(r0, 1)                        @ r0<- CCBB
4691    mov     r9, rINST, lsr #8           @ r9<- AA
4692    and     r2, r0, #255                @ r2<- BB
4693    mov     r3, r0, lsr #8              @ r3<- CC
4694    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4695    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4696    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4697    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4698    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4699    .if 1
4700    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4701    beq     common_errDivideByZero
4702    .endif
4703    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4704
4705                               @ optional op; may set condition codes
4706    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4708    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4709    GOTO_OPCODE(ip)                     @ jump to next instruction
4710    /* 14-17 instructions */
4711
4712
4713/* ------------------------------ */
4714    .balign 64
4715.L_OP_AND_LONG: /* 0xa0 */
4716/* File: armv5te/OP_AND_LONG.S */
4717/* File: armv5te/binopWide.S */
4718    /*
4719     * Generic 64-bit binary operation.  Provide an "instr" line that
4720     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4721     * This could be an ARM instruction or a function call.  (If the result
4722     * comes back in a register other than r0, you can override "result".)
4723     *
4724     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4725     * vCC (r1).  Useful for integer division and modulus.
4726     *
4727     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4728     *      xor-long, add-double, sub-double, mul-double, div-double,
4729     *      rem-double
4730     *
4731     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4732     */
4733    /* binop vAA, vBB, vCC */
4734    FETCH(r0, 1)                        @ r0<- CCBB
4735    mov     r9, rINST, lsr #8           @ r9<- AA
4736    and     r2, r0, #255                @ r2<- BB
4737    mov     r3, r0, lsr #8              @ r3<- CC
4738    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4739    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4740    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4741    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4742    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4743    .if 0
4744    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4745    beq     common_errDivideByZero
4746    .endif
4747    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4748
4749    and     r0, r0, r2                           @ optional op; may set condition codes
4750    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4752    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4753    GOTO_OPCODE(ip)                     @ jump to next instruction
4754    /* 14-17 instructions */
4755
4756
4757/* ------------------------------ */
4758    .balign 64
4759.L_OP_OR_LONG: /* 0xa1 */
4760/* File: armv5te/OP_OR_LONG.S */
4761/* File: armv5te/binopWide.S */
4762    /*
4763     * Generic 64-bit binary operation.  Provide an "instr" line that
4764     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4765     * This could be an ARM instruction or a function call.  (If the result
4766     * comes back in a register other than r0, you can override "result".)
4767     *
4768     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4769     * vCC (r1).  Useful for integer division and modulus.
4770     *
4771     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4772     *      xor-long, add-double, sub-double, mul-double, div-double,
4773     *      rem-double
4774     *
4775     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4776     */
4777    /* binop vAA, vBB, vCC */
4778    FETCH(r0, 1)                        @ r0<- CCBB
4779    mov     r9, rINST, lsr #8           @ r9<- AA
4780    and     r2, r0, #255                @ r2<- BB
4781    mov     r3, r0, lsr #8              @ r3<- CC
4782    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4783    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4784    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4785    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4786    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4787    .if 0
4788    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4789    beq     common_errDivideByZero
4790    .endif
4791    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4792
4793    orr     r0, r0, r2                           @ optional op; may set condition codes
4794    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4796    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4797    GOTO_OPCODE(ip)                     @ jump to next instruction
4798    /* 14-17 instructions */
4799
4800
4801/* ------------------------------ */
4802    .balign 64
4803.L_OP_XOR_LONG: /* 0xa2 */
4804/* File: armv5te/OP_XOR_LONG.S */
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 0
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    eor     r0, r0, r2                           @ optional op; may set condition codes
4838    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4840    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4841    GOTO_OPCODE(ip)                     @ jump to next instruction
4842    /* 14-17 instructions */
4843
4844
4845/* ------------------------------ */
4846    .balign 64
4847.L_OP_SHL_LONG: /* 0xa3 */
4848/* File: armv5te/OP_SHL_LONG.S */
4849    /*
4850     * Long integer shift.  This is different from the generic 32/64-bit
4851     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4852     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4853     * 6 bits of the shift distance.
4854     */
4855    /* shl-long vAA, vBB, vCC */
4856    FETCH(r0, 1)                        @ r0<- CCBB
4857    mov     r9, rINST, lsr #8           @ r9<- AA
4858    and     r3, r0, #255                @ r3<- BB
4859    mov     r0, r0, lsr #8              @ r0<- CC
4860    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4861    GET_VREG(r2, r0)                    @ r2<- vCC
4862    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4863    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4864    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4865
4866    mov     r1, r1, asl r2              @  r1<- r1 << r2
4867    rsb     r3, r2, #32                 @  r3<- 32 - r2
4868    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4869    subs    ip, r2, #32                 @  ip<- r2 - 32
4870    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4871    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4872    b       .LOP_SHL_LONG_finish
4873
4874/* ------------------------------ */
4875    .balign 64
4876.L_OP_SHR_LONG: /* 0xa4 */
4877/* File: armv5te/OP_SHR_LONG.S */
4878    /*
4879     * Long integer shift.  This is different from the generic 32/64-bit
4880     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4881     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4882     * 6 bits of the shift distance.
4883     */
4884    /* shr-long vAA, vBB, vCC */
4885    FETCH(r0, 1)                        @ r0<- CCBB
4886    mov     r9, rINST, lsr #8           @ r9<- AA
4887    and     r3, r0, #255                @ r3<- BB
4888    mov     r0, r0, lsr #8              @ r0<- CC
4889    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4890    GET_VREG(r2, r0)                    @ r2<- vCC
4891    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4892    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4893    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4894
4895    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4896    rsb     r3, r2, #32                 @  r3<- 32 - r2
4897    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4898    subs    ip, r2, #32                 @  ip<- r2 - 32
4899    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4900    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4901    b       .LOP_SHR_LONG_finish
4902
4903/* ------------------------------ */
4904    .balign 64
4905.L_OP_USHR_LONG: /* 0xa5 */
4906/* File: armv5te/OP_USHR_LONG.S */
4907    /*
4908     * Long integer shift.  This is different from the generic 32/64-bit
4909     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4910     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4911     * 6 bits of the shift distance.
4912     */
4913    /* ushr-long vAA, vBB, vCC */
4914    FETCH(r0, 1)                        @ r0<- CCBB
4915    mov     r9, rINST, lsr #8           @ r9<- AA
4916    and     r3, r0, #255                @ r3<- BB
4917    mov     r0, r0, lsr #8              @ r0<- CC
4918    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4919    GET_VREG(r2, r0)                    @ r2<- vCC
4920    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4921    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4922    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4923
4924    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4925    rsb     r3, r2, #32                 @  r3<- 32 - r2
4926    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4927    subs    ip, r2, #32                 @  ip<- r2 - 32
4928    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4929    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4930    b       .LOP_USHR_LONG_finish
4931
4932/* ------------------------------ */
4933    .balign 64
4934.L_OP_ADD_FLOAT: /* 0xa6 */
4935/* File: arm-vfp/OP_ADD_FLOAT.S */
4936/* File: arm-vfp/fbinop.S */
4937    /*
4938     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4939     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4940     * use the "softfp" ABI, this must be an instruction, not a function call.
4941     *
4942     * For: add-float, sub-float, mul-float, div-float
4943     */
4944    /* floatop vAA, vBB, vCC */
4945    FETCH(r0, 1)                        @ r0<- CCBB
4946    mov     r9, rINST, lsr #8           @ r9<- AA
4947    mov     r3, r0, lsr #8              @ r3<- CC
4948    and     r2, r0, #255                @ r2<- BB
4949    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4950    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4951    flds    s1, [r3]                    @ s1<- vCC
4952    flds    s0, [r2]                    @ s0<- vBB
4953
4954    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4955    fadds   s2, s0, s1                              @ s2<- op
4956    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4957    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4958    fsts    s2, [r9]                    @ vAA<- s2
4959    GOTO_OPCODE(ip)                     @ jump to next instruction
4960
4961
4962/* ------------------------------ */
4963    .balign 64
4964.L_OP_SUB_FLOAT: /* 0xa7 */
4965/* File: arm-vfp/OP_SUB_FLOAT.S */
4966/* File: arm-vfp/fbinop.S */
4967    /*
4968     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4969     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4970     * use the "softfp" ABI, this must be an instruction, not a function call.
4971     *
4972     * For: add-float, sub-float, mul-float, div-float
4973     */
4974    /* floatop vAA, vBB, vCC */
4975    FETCH(r0, 1)                        @ r0<- CCBB
4976    mov     r9, rINST, lsr #8           @ r9<- AA
4977    mov     r3, r0, lsr #8              @ r3<- CC
4978    and     r2, r0, #255                @ r2<- BB
4979    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4980    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4981    flds    s1, [r3]                    @ s1<- vCC
4982    flds    s0, [r2]                    @ s0<- vBB
4983
4984    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4985    fsubs   s2, s0, s1                              @ s2<- op
4986    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4987    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4988    fsts    s2, [r9]                    @ vAA<- s2
4989    GOTO_OPCODE(ip)                     @ jump to next instruction
4990
4991
4992/* ------------------------------ */
4993    .balign 64
4994.L_OP_MUL_FLOAT: /* 0xa8 */
4995/* File: arm-vfp/OP_MUL_FLOAT.S */
4996/* File: arm-vfp/fbinop.S */
4997    /*
4998     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4999     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5000     * use the "softfp" ABI, this must be an instruction, not a function call.
5001     *
5002     * For: add-float, sub-float, mul-float, div-float
5003     */
5004    /* floatop vAA, vBB, vCC */
5005    FETCH(r0, 1)                        @ r0<- CCBB
5006    mov     r9, rINST, lsr #8           @ r9<- AA
5007    mov     r3, r0, lsr #8              @ r3<- CC
5008    and     r2, r0, #255                @ r2<- BB
5009    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5010    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5011    flds    s1, [r3]                    @ s1<- vCC
5012    flds    s0, [r2]                    @ s0<- vBB
5013
5014    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5015    fmuls   s2, s0, s1                              @ s2<- op
5016    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5017    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5018    fsts    s2, [r9]                    @ vAA<- s2
5019    GOTO_OPCODE(ip)                     @ jump to next instruction
5020
5021
5022/* ------------------------------ */
5023    .balign 64
5024.L_OP_DIV_FLOAT: /* 0xa9 */
5025/* File: arm-vfp/OP_DIV_FLOAT.S */
5026/* File: arm-vfp/fbinop.S */
5027    /*
5028     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5029     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5030     * use the "softfp" ABI, this must be an instruction, not a function call.
5031     *
5032     * For: add-float, sub-float, mul-float, div-float
5033     */
5034    /* floatop vAA, vBB, vCC */
5035    FETCH(r0, 1)                        @ r0<- CCBB
5036    mov     r9, rINST, lsr #8           @ r9<- AA
5037    mov     r3, r0, lsr #8              @ r3<- CC
5038    and     r2, r0, #255                @ r2<- BB
5039    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5040    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5041    flds    s1, [r3]                    @ s1<- vCC
5042    flds    s0, [r2]                    @ s0<- vBB
5043
5044    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5045    fdivs   s2, s0, s1                              @ s2<- op
5046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5047    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5048    fsts    s2, [r9]                    @ vAA<- s2
5049    GOTO_OPCODE(ip)                     @ jump to next instruction
5050
5051
5052/* ------------------------------ */
5053    .balign 64
5054.L_OP_REM_FLOAT: /* 0xaa */
5055/* File: armv5te/OP_REM_FLOAT.S */
5056/* EABI doesn't define a float remainder function, but libm does */
5057/* File: armv5te/binop.S */
5058    /*
5059     * Generic 32-bit binary operation.  Provide an "instr" line that
5060     * specifies an instruction that performs "result = r0 op r1".
5061     * This could be an ARM instruction or a function call.  (If the result
5062     * comes back in a register other than r0, you can override "result".)
5063     *
5064     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5065     * vCC (r1).  Useful for integer division and modulus.  Note that we
5066     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5067     * handles it correctly.
5068     *
5069     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5070     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5071     *      mul-float, div-float, rem-float
5072     */
5073    /* binop vAA, vBB, vCC */
5074    FETCH(r0, 1)                        @ r0<- CCBB
5075    mov     r9, rINST, lsr #8           @ r9<- AA
5076    mov     r3, r0, lsr #8              @ r3<- CC
5077    and     r2, r0, #255                @ r2<- BB
5078    GET_VREG(r1, r3)                    @ r1<- vCC
5079    GET_VREG(r0, r2)                    @ r0<- vBB
5080    .if 0
5081    cmp     r1, #0                      @ is second operand zero?
5082    beq     common_errDivideByZero
5083    .endif
5084
5085    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5086                               @ optional op; may set condition codes
5087    bl      fmodf                              @ r0<- op, r0-r3 changed
5088    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5089    SET_VREG(r0, r9)               @ vAA<- r0
5090    GOTO_OPCODE(ip)                     @ jump to next instruction
5091    /* 11-14 instructions */
5092
5093
5094/* ------------------------------ */
5095    .balign 64
5096.L_OP_ADD_DOUBLE: /* 0xab */
5097/* File: arm-vfp/OP_ADD_DOUBLE.S */
5098/* File: arm-vfp/fbinopWide.S */
5099    /*
5100     * Generic 64-bit double-precision floating point binary operation.
5101     * Provide an "instr" line that specifies an instruction that performs
5102     * "d2 = d0 op d1".
5103     *
5104     * for: add-double, sub-double, mul-double, div-double
5105     */
5106    /* doubleop vAA, vBB, vCC */
5107    FETCH(r0, 1)                        @ r0<- CCBB
5108    mov     r9, rINST, lsr #8           @ r9<- AA
5109    mov     r3, r0, lsr #8              @ r3<- CC
5110    and     r2, r0, #255                @ r2<- BB
5111    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5112    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5113    fldd    d1, [r3]                    @ d1<- vCC
5114    fldd    d0, [r2]                    @ d0<- vBB
5115
5116    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5117    faddd   d2, d0, d1                              @ s2<- op
5118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5119    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5120    fstd    d2, [r9]                    @ vAA<- d2
5121    GOTO_OPCODE(ip)                     @ jump to next instruction
5122
5123
5124/* ------------------------------ */
5125    .balign 64
5126.L_OP_SUB_DOUBLE: /* 0xac */
5127/* File: arm-vfp/OP_SUB_DOUBLE.S */
5128/* File: arm-vfp/fbinopWide.S */
5129    /*
5130     * Generic 64-bit double-precision floating point binary operation.
5131     * Provide an "instr" line that specifies an instruction that performs
5132     * "d2 = d0 op d1".
5133     *
5134     * for: add-double, sub-double, mul-double, div-double
5135     */
5136    /* doubleop vAA, vBB, vCC */
5137    FETCH(r0, 1)                        @ r0<- CCBB
5138    mov     r9, rINST, lsr #8           @ r9<- AA
5139    mov     r3, r0, lsr #8              @ r3<- CC
5140    and     r2, r0, #255                @ r2<- BB
5141    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5142    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5143    fldd    d1, [r3]                    @ d1<- vCC
5144    fldd    d0, [r2]                    @ d0<- vBB
5145
5146    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5147    fsubd   d2, d0, d1                              @ s2<- op
5148    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5149    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5150    fstd    d2, [r9]                    @ vAA<- d2
5151    GOTO_OPCODE(ip)                     @ jump to next instruction
5152
5153
5154/* ------------------------------ */
5155    .balign 64
5156.L_OP_MUL_DOUBLE: /* 0xad */
5157/* File: arm-vfp/OP_MUL_DOUBLE.S */
5158/* File: arm-vfp/fbinopWide.S */
5159    /*
5160     * Generic 64-bit double-precision floating point binary operation.
5161     * Provide an "instr" line that specifies an instruction that performs
5162     * "d2 = d0 op d1".
5163     *
5164     * for: add-double, sub-double, mul-double, div-double
5165     */
5166    /* doubleop 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    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5172    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5173    fldd    d1, [r3]                    @ d1<- vCC
5174    fldd    d0, [r2]                    @ d0<- vBB
5175
5176    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5177    fmuld   d2, d0, d1                              @ s2<- op
5178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5179    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5180    fstd    d2, [r9]                    @ vAA<- d2
5181    GOTO_OPCODE(ip)                     @ jump to next instruction
5182
5183
5184/* ------------------------------ */
5185    .balign 64
5186.L_OP_DIV_DOUBLE: /* 0xae */
5187/* File: arm-vfp/OP_DIV_DOUBLE.S */
5188/* File: arm-vfp/fbinopWide.S */
5189    /*
5190     * Generic 64-bit double-precision floating point binary operation.
5191     * Provide an "instr" line that specifies an instruction that performs
5192     * "d2 = d0 op d1".
5193     *
5194     * for: add-double, sub-double, mul-double, div-double
5195     */
5196    /* doubleop vAA, vBB, vCC */
5197    FETCH(r0, 1)                        @ r0<- CCBB
5198    mov     r9, rINST, lsr #8           @ r9<- AA
5199    mov     r3, r0, lsr #8              @ r3<- CC
5200    and     r2, r0, #255                @ r2<- BB
5201    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5202    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5203    fldd    d1, [r3]                    @ d1<- vCC
5204    fldd    d0, [r2]                    @ d0<- vBB
5205
5206    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5207    fdivd   d2, d0, d1                              @ s2<- op
5208    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5209    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5210    fstd    d2, [r9]                    @ vAA<- d2
5211    GOTO_OPCODE(ip)                     @ jump to next instruction
5212
5213
5214/* ------------------------------ */
5215    .balign 64
5216.L_OP_REM_DOUBLE: /* 0xaf */
5217/* File: armv5te/OP_REM_DOUBLE.S */
5218/* EABI doesn't define a double remainder function, but libm does */
5219/* File: armv5te/binopWide.S */
5220    /*
5221     * Generic 64-bit binary operation.  Provide an "instr" line that
5222     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5223     * This could be an ARM instruction or a function call.  (If the result
5224     * comes back in a register other than r0, you can override "result".)
5225     *
5226     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5227     * vCC (r1).  Useful for integer division and modulus.
5228     *
5229     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5230     *      xor-long, add-double, sub-double, mul-double, div-double,
5231     *      rem-double
5232     *
5233     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5234     */
5235    /* binop vAA, vBB, vCC */
5236    FETCH(r0, 1)                        @ r0<- CCBB
5237    mov     r9, rINST, lsr #8           @ r9<- AA
5238    and     r2, r0, #255                @ r2<- BB
5239    mov     r3, r0, lsr #8              @ r3<- CC
5240    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5241    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5242    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5243    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5244    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5245    .if 0
5246    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5247    beq     common_errDivideByZero
5248    .endif
5249    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5250
5251                               @ optional op; may set condition codes
5252    bl      fmod                              @ result<- op, r0-r3 changed
5253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5254    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5255    GOTO_OPCODE(ip)                     @ jump to next instruction
5256    /* 14-17 instructions */
5257
5258
5259/* ------------------------------ */
5260    .balign 64
5261.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5262/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5263/* File: armv6t2/binop2addr.S */
5264    /*
5265     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5266     * that specifies an instruction that performs "result = r0 op r1".
5267     * This could be an ARM instruction or a function call.  (If the result
5268     * comes back in a register other than r0, you can override "result".)
5269     *
5270     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5271     * vCC (r1).  Useful for integer division and modulus.
5272     *
5273     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5274     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5275     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5276     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5277     */
5278    /* binop/2addr vA, vB */
5279    mov     r3, rINST, lsr #12          @ r3<- B
5280    ubfx    r9, rINST, #8, #4           @ r9<- A
5281    GET_VREG(r1, r3)                    @ r1<- vB
5282    GET_VREG(r0, r9)                    @ r0<- vA
5283    .if 0
5284    cmp     r1, #0                      @ is second operand zero?
5285    beq     common_errDivideByZero
5286    .endif
5287    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5288
5289                               @ optional op; may set condition codes
5290    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5291    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5292    SET_VREG(r0, r9)               @ vAA<- r0
5293    GOTO_OPCODE(ip)                     @ jump to next instruction
5294    /* 10-13 instructions */
5295
5296
5297/* ------------------------------ */
5298    .balign 64
5299.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5300/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5301/* File: armv6t2/binop2addr.S */
5302    /*
5303     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5304     * that specifies an instruction that performs "result = r0 op r1".
5305     * This could be an ARM instruction or a function call.  (If the result
5306     * comes back in a register other than r0, you can override "result".)
5307     *
5308     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5309     * vCC (r1).  Useful for integer division and modulus.
5310     *
5311     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5312     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5313     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5314     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5315     */
5316    /* binop/2addr vA, vB */
5317    mov     r3, rINST, lsr #12          @ r3<- B
5318    ubfx    r9, rINST, #8, #4           @ r9<- A
5319    GET_VREG(r1, r3)                    @ r1<- vB
5320    GET_VREG(r0, r9)                    @ r0<- vA
5321    .if 0
5322    cmp     r1, #0                      @ is second operand zero?
5323    beq     common_errDivideByZero
5324    .endif
5325    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5326
5327                               @ optional op; may set condition codes
5328    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5329    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5330    SET_VREG(r0, r9)               @ vAA<- r0
5331    GOTO_OPCODE(ip)                     @ jump to next instruction
5332    /* 10-13 instructions */
5333
5334
5335/* ------------------------------ */
5336    .balign 64
5337.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5338/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5339/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5340/* File: armv6t2/binop2addr.S */
5341    /*
5342     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5343     * that specifies an instruction that performs "result = r0 op r1".
5344     * This could be an ARM instruction or a function call.  (If the result
5345     * comes back in a register other than r0, you can override "result".)
5346     *
5347     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5348     * vCC (r1).  Useful for integer division and modulus.
5349     *
5350     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5351     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5352     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5353     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5354     */
5355    /* binop/2addr vA, vB */
5356    mov     r3, rINST, lsr #12          @ r3<- B
5357    ubfx    r9, rINST, #8, #4           @ r9<- A
5358    GET_VREG(r1, r3)                    @ r1<- vB
5359    GET_VREG(r0, r9)                    @ r0<- vA
5360    .if 0
5361    cmp     r1, #0                      @ is second operand zero?
5362    beq     common_errDivideByZero
5363    .endif
5364    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5365
5366                               @ optional op; may set condition codes
5367    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5369    SET_VREG(r0, r9)               @ vAA<- r0
5370    GOTO_OPCODE(ip)                     @ jump to next instruction
5371    /* 10-13 instructions */
5372
5373
5374/* ------------------------------ */
5375    .balign 64
5376.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5377/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5378/* File: armv6t2/binop2addr.S */
5379    /*
5380     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5381     * that specifies an instruction that performs "result = r0 op r1".
5382     * This could be an ARM instruction or a function call.  (If the result
5383     * comes back in a register other than r0, you can override "result".)
5384     *
5385     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5386     * vCC (r1).  Useful for integer division and modulus.
5387     *
5388     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5389     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5390     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5391     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5392     */
5393    /* binop/2addr vA, vB */
5394    mov     r3, rINST, lsr #12          @ r3<- B
5395    ubfx    r9, rINST, #8, #4           @ r9<- A
5396    GET_VREG(r1, r3)                    @ r1<- vB
5397    GET_VREG(r0, r9)                    @ r0<- vA
5398    .if 1
5399    cmp     r1, #0                      @ is second operand zero?
5400    beq     common_errDivideByZero
5401    .endif
5402    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5403
5404                               @ optional op; may set condition codes
5405    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5406    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5407    SET_VREG(r0, r9)               @ vAA<- r0
5408    GOTO_OPCODE(ip)                     @ jump to next instruction
5409    /* 10-13 instructions */
5410
5411
5412/* ------------------------------ */
5413    .balign 64
5414.L_OP_REM_INT_2ADDR: /* 0xb4 */
5415/* File: armv6t2/OP_REM_INT_2ADDR.S */
5416/* idivmod returns quotient in r0 and remainder in r1 */
5417/* File: armv6t2/binop2addr.S */
5418    /*
5419     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5420     * that specifies an instruction that performs "result = r0 op r1".
5421     * This could be an ARM instruction or a function call.  (If the result
5422     * comes back in a register other than r0, you can override "result".)
5423     *
5424     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5425     * vCC (r1).  Useful for integer division and modulus.
5426     *
5427     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5428     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5429     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5430     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5431     */
5432    /* binop/2addr vA, vB */
5433    mov     r3, rINST, lsr #12          @ r3<- B
5434    ubfx    r9, rINST, #8, #4           @ r9<- A
5435    GET_VREG(r1, r3)                    @ r1<- vB
5436    GET_VREG(r0, r9)                    @ r0<- vA
5437    .if 1
5438    cmp     r1, #0                      @ is second operand zero?
5439    beq     common_errDivideByZero
5440    .endif
5441    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5442
5443                               @ optional op; may set condition codes
5444    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5445    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5446    SET_VREG(r1, r9)               @ vAA<- r1
5447    GOTO_OPCODE(ip)                     @ jump to next instruction
5448    /* 10-13 instructions */
5449
5450
5451/* ------------------------------ */
5452    .balign 64
5453.L_OP_AND_INT_2ADDR: /* 0xb5 */
5454/* File: armv6t2/OP_AND_INT_2ADDR.S */
5455/* File: armv6t2/binop2addr.S */
5456    /*
5457     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5458     * that specifies an instruction that performs "result = r0 op r1".
5459     * This could be an ARM instruction or a function call.  (If the result
5460     * comes back in a register other than r0, you can override "result".)
5461     *
5462     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5463     * vCC (r1).  Useful for integer division and modulus.
5464     *
5465     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5466     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5467     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5468     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5469     */
5470    /* binop/2addr vA, vB */
5471    mov     r3, rINST, lsr #12          @ r3<- B
5472    ubfx    r9, rINST, #8, #4           @ r9<- A
5473    GET_VREG(r1, r3)                    @ r1<- vB
5474    GET_VREG(r0, r9)                    @ r0<- vA
5475    .if 0
5476    cmp     r1, #0                      @ is second operand zero?
5477    beq     common_errDivideByZero
5478    .endif
5479    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5480
5481                               @ optional op; may set condition codes
5482    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5483    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5484    SET_VREG(r0, r9)               @ vAA<- r0
5485    GOTO_OPCODE(ip)                     @ jump to next instruction
5486    /* 10-13 instructions */
5487
5488
5489/* ------------------------------ */
5490    .balign 64
5491.L_OP_OR_INT_2ADDR: /* 0xb6 */
5492/* File: armv6t2/OP_OR_INT_2ADDR.S */
5493/* File: armv6t2/binop2addr.S */
5494    /*
5495     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5496     * that specifies an instruction that performs "result = r0 op r1".
5497     * This could be an ARM instruction or a function call.  (If the result
5498     * comes back in a register other than r0, you can override "result".)
5499     *
5500     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5501     * vCC (r1).  Useful for integer division and modulus.
5502     *
5503     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5504     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5505     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5506     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5507     */
5508    /* binop/2addr vA, vB */
5509    mov     r3, rINST, lsr #12          @ r3<- B
5510    ubfx    r9, rINST, #8, #4           @ r9<- A
5511    GET_VREG(r1, r3)                    @ r1<- vB
5512    GET_VREG(r0, r9)                    @ r0<- vA
5513    .if 0
5514    cmp     r1, #0                      @ is second operand zero?
5515    beq     common_errDivideByZero
5516    .endif
5517    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5518
5519                               @ optional op; may set condition codes
5520    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5521    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5522    SET_VREG(r0, r9)               @ vAA<- r0
5523    GOTO_OPCODE(ip)                     @ jump to next instruction
5524    /* 10-13 instructions */
5525
5526
5527/* ------------------------------ */
5528    .balign 64
5529.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5530/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5531/* File: armv6t2/binop2addr.S */
5532    /*
5533     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5534     * that specifies an instruction that performs "result = r0 op r1".
5535     * This could be an ARM instruction or a function call.  (If the result
5536     * comes back in a register other than r0, you can override "result".)
5537     *
5538     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5539     * vCC (r1).  Useful for integer division and modulus.
5540     *
5541     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5542     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5543     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5544     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5545     */
5546    /* binop/2addr vA, vB */
5547    mov     r3, rINST, lsr #12          @ r3<- B
5548    ubfx    r9, rINST, #8, #4           @ r9<- A
5549    GET_VREG(r1, r3)                    @ r1<- vB
5550    GET_VREG(r0, r9)                    @ r0<- vA
5551    .if 0
5552    cmp     r1, #0                      @ is second operand zero?
5553    beq     common_errDivideByZero
5554    .endif
5555    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5556
5557                               @ optional op; may set condition codes
5558    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5559    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5560    SET_VREG(r0, r9)               @ vAA<- r0
5561    GOTO_OPCODE(ip)                     @ jump to next instruction
5562    /* 10-13 instructions */
5563
5564
5565/* ------------------------------ */
5566    .balign 64
5567.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5568/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5569/* File: armv6t2/binop2addr.S */
5570    /*
5571     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5572     * that specifies an instruction that performs "result = r0 op r1".
5573     * This could be an ARM instruction or a function call.  (If the result
5574     * comes back in a register other than r0, you can override "result".)
5575     *
5576     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5577     * vCC (r1).  Useful for integer division and modulus.
5578     *
5579     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5580     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5581     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5582     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5583     */
5584    /* binop/2addr vA, vB */
5585    mov     r3, rINST, lsr #12          @ r3<- B
5586    ubfx    r9, rINST, #8, #4           @ r9<- A
5587    GET_VREG(r1, r3)                    @ r1<- vB
5588    GET_VREG(r0, r9)                    @ r0<- vA
5589    .if 0
5590    cmp     r1, #0                      @ is second operand zero?
5591    beq     common_errDivideByZero
5592    .endif
5593    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5594
5595    and     r1, r1, #31                           @ optional op; may set condition codes
5596    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5597    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5598    SET_VREG(r0, r9)               @ vAA<- r0
5599    GOTO_OPCODE(ip)                     @ jump to next instruction
5600    /* 10-13 instructions */
5601
5602
5603/* ------------------------------ */
5604    .balign 64
5605.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5606/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5607/* File: armv6t2/binop2addr.S */
5608    /*
5609     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5610     * that specifies an instruction that performs "result = r0 op r1".
5611     * This could be an ARM instruction or a function call.  (If the result
5612     * comes back in a register other than r0, you can override "result".)
5613     *
5614     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5615     * vCC (r1).  Useful for integer division and modulus.
5616     *
5617     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5618     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5619     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5620     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5621     */
5622    /* binop/2addr vA, vB */
5623    mov     r3, rINST, lsr #12          @ r3<- B
5624    ubfx    r9, rINST, #8, #4           @ r9<- A
5625    GET_VREG(r1, r3)                    @ r1<- vB
5626    GET_VREG(r0, r9)                    @ r0<- vA
5627    .if 0
5628    cmp     r1, #0                      @ is second operand zero?
5629    beq     common_errDivideByZero
5630    .endif
5631    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5632
5633    and     r1, r1, #31                           @ optional op; may set condition codes
5634    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5635    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5636    SET_VREG(r0, r9)               @ vAA<- r0
5637    GOTO_OPCODE(ip)                     @ jump to next instruction
5638    /* 10-13 instructions */
5639
5640
5641/* ------------------------------ */
5642    .balign 64
5643.L_OP_USHR_INT_2ADDR: /* 0xba */
5644/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5645/* File: armv6t2/binop2addr.S */
5646    /*
5647     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5648     * that specifies an instruction that performs "result = r0 op r1".
5649     * This could be an ARM instruction or a function call.  (If the result
5650     * comes back in a register other than r0, you can override "result".)
5651     *
5652     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5653     * vCC (r1).  Useful for integer division and modulus.
5654     *
5655     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5656     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5657     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5658     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5659     */
5660    /* binop/2addr vA, vB */
5661    mov     r3, rINST, lsr #12          @ r3<- B
5662    ubfx    r9, rINST, #8, #4           @ r9<- A
5663    GET_VREG(r1, r3)                    @ r1<- vB
5664    GET_VREG(r0, r9)                    @ r0<- vA
5665    .if 0
5666    cmp     r1, #0                      @ is second operand zero?
5667    beq     common_errDivideByZero
5668    .endif
5669    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5670
5671    and     r1, r1, #31                           @ optional op; may set condition codes
5672    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5673    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5674    SET_VREG(r0, r9)               @ vAA<- r0
5675    GOTO_OPCODE(ip)                     @ jump to next instruction
5676    /* 10-13 instructions */
5677
5678
5679/* ------------------------------ */
5680    .balign 64
5681.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5682/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5683/* File: armv6t2/binopWide2addr.S */
5684    /*
5685     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5686     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5687     * This could be an ARM instruction or a function call.  (If the result
5688     * comes back in a register other than r0, you can override "result".)
5689     *
5690     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5691     * vCC (r1).  Useful for integer division and modulus.
5692     *
5693     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5694     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5695     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5696     *      rem-double/2addr
5697     */
5698    /* binop/2addr vA, vB */
5699    mov     r1, rINST, lsr #12          @ r1<- B
5700    ubfx    r9, rINST, #8, #4           @ r9<- A
5701    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5702    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5703    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5704    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5705    .if 0
5706    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5707    beq     common_errDivideByZero
5708    .endif
5709    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5710
5711    adds    r0, r0, r2                           @ optional op; may set condition codes
5712    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5713    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5714    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5715    GOTO_OPCODE(ip)                     @ jump to next instruction
5716    /* 12-15 instructions */
5717
5718
5719/* ------------------------------ */
5720    .balign 64
5721.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5722/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5723/* File: armv6t2/binopWide2addr.S */
5724    /*
5725     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5726     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5727     * This could be an ARM instruction or a function call.  (If the result
5728     * comes back in a register other than r0, you can override "result".)
5729     *
5730     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5731     * vCC (r1).  Useful for integer division and modulus.
5732     *
5733     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5734     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5735     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5736     *      rem-double/2addr
5737     */
5738    /* binop/2addr vA, vB */
5739    mov     r1, rINST, lsr #12          @ r1<- B
5740    ubfx    r9, rINST, #8, #4           @ r9<- A
5741    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5742    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5743    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5744    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5745    .if 0
5746    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5747    beq     common_errDivideByZero
5748    .endif
5749    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5750
5751    subs    r0, r0, r2                           @ optional op; may set condition codes
5752    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5754    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5755    GOTO_OPCODE(ip)                     @ jump to next instruction
5756    /* 12-15 instructions */
5757
5758
5759/* ------------------------------ */
5760    .balign 64
5761.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5762/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5763    /*
5764     * Signed 64-bit integer multiply, "/2addr" version.
5765     *
5766     * See OP_MUL_LONG for an explanation.
5767     *
5768     * We get a little tight on registers, so to avoid looking up &fp[A]
5769     * again we stuff it into rINST.
5770     */
5771    /* mul-long/2addr vA, vB */
5772    mov     r1, rINST, lsr #12          @ r1<- B
5773    ubfx    r9, rINST, #8, #4           @ r9<- A
5774    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5775    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5776    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5777    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5778    mul     ip, r2, r1                  @  ip<- ZxW
5779    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5780    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5781    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5782    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5783    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5784    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5785    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5786    GOTO_OPCODE(ip)                     @ jump to next instruction
5787
5788/* ------------------------------ */
5789    .balign 64
5790.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5791/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5792/* File: armv6t2/binopWide2addr.S */
5793    /*
5794     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5795     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5796     * This could be an ARM instruction or a function call.  (If the result
5797     * comes back in a register other than r0, you can override "result".)
5798     *
5799     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5800     * vCC (r1).  Useful for integer division and modulus.
5801     *
5802     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5803     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5804     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5805     *      rem-double/2addr
5806     */
5807    /* binop/2addr vA, vB */
5808    mov     r1, rINST, lsr #12          @ r1<- B
5809    ubfx    r9, rINST, #8, #4           @ r9<- A
5810    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5811    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5812    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5813    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5814    .if 1
5815    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5816    beq     common_errDivideByZero
5817    .endif
5818    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5819
5820                               @ optional op; may set condition codes
5821    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5823    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5824    GOTO_OPCODE(ip)                     @ jump to next instruction
5825    /* 12-15 instructions */
5826
5827
5828/* ------------------------------ */
5829    .balign 64
5830.L_OP_REM_LONG_2ADDR: /* 0xbf */
5831/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5832/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5833/* File: armv6t2/binopWide2addr.S */
5834    /*
5835     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5836     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5837     * This could be an ARM instruction or a function call.  (If the result
5838     * comes back in a register other than r0, you can override "result".)
5839     *
5840     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5841     * vCC (r1).  Useful for integer division and modulus.
5842     *
5843     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5844     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5845     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5846     *      rem-double/2addr
5847     */
5848    /* binop/2addr vA, vB */
5849    mov     r1, rINST, lsr #12          @ r1<- B
5850    ubfx    r9, rINST, #8, #4           @ r9<- A
5851    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5852    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5853    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5854    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5855    .if 1
5856    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5857    beq     common_errDivideByZero
5858    .endif
5859    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5860
5861                               @ optional op; may set condition codes
5862    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5863    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5864    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5865    GOTO_OPCODE(ip)                     @ jump to next instruction
5866    /* 12-15 instructions */
5867
5868
5869/* ------------------------------ */
5870    .balign 64
5871.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5872/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5873/* File: armv6t2/binopWide2addr.S */
5874    /*
5875     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5876     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5877     * This could be an ARM instruction or a function call.  (If the result
5878     * comes back in a register other than r0, you can override "result".)
5879     *
5880     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5881     * vCC (r1).  Useful for integer division and modulus.
5882     *
5883     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5884     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5885     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5886     *      rem-double/2addr
5887     */
5888    /* binop/2addr vA, vB */
5889    mov     r1, rINST, lsr #12          @ r1<- B
5890    ubfx    r9, rINST, #8, #4           @ r9<- A
5891    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5892    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5893    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5894    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5895    .if 0
5896    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5897    beq     common_errDivideByZero
5898    .endif
5899    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5900
5901    and     r0, r0, r2                           @ optional op; may set condition codes
5902    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5903    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5904    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5905    GOTO_OPCODE(ip)                     @ jump to next instruction
5906    /* 12-15 instructions */
5907
5908
5909/* ------------------------------ */
5910    .balign 64
5911.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5912/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5913/* File: armv6t2/binopWide2addr.S */
5914    /*
5915     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5916     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5917     * This could be an ARM instruction or a function call.  (If the result
5918     * comes back in a register other than r0, you can override "result".)
5919     *
5920     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5921     * vCC (r1).  Useful for integer division and modulus.
5922     *
5923     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5924     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5925     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5926     *      rem-double/2addr
5927     */
5928    /* binop/2addr vA, vB */
5929    mov     r1, rINST, lsr #12          @ r1<- B
5930    ubfx    r9, rINST, #8, #4           @ r9<- A
5931    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5932    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5933    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5934    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5935    .if 0
5936    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5937    beq     common_errDivideByZero
5938    .endif
5939    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5940
5941    orr     r0, r0, r2                           @ optional op; may set condition codes
5942    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5943    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5944    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5945    GOTO_OPCODE(ip)                     @ jump to next instruction
5946    /* 12-15 instructions */
5947
5948
5949/* ------------------------------ */
5950    .balign 64
5951.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5952/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5953/* File: armv6t2/binopWide2addr.S */
5954    /*
5955     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5956     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5957     * This could be an ARM instruction or a function call.  (If the result
5958     * comes back in a register other than r0, you can override "result".)
5959     *
5960     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5961     * vCC (r1).  Useful for integer division and modulus.
5962     *
5963     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5964     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5965     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5966     *      rem-double/2addr
5967     */
5968    /* binop/2addr vA, vB */
5969    mov     r1, rINST, lsr #12          @ r1<- B
5970    ubfx    r9, rINST, #8, #4           @ r9<- A
5971    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5972    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5973    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5974    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5975    .if 0
5976    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5977    beq     common_errDivideByZero
5978    .endif
5979    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5980
5981    eor     r0, r0, r2                           @ optional op; may set condition codes
5982    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5984    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5985    GOTO_OPCODE(ip)                     @ jump to next instruction
5986    /* 12-15 instructions */
5987
5988
5989/* ------------------------------ */
5990    .balign 64
5991.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5992/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
5993    /*
5994     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5995     * 32-bit shift distance.
5996     */
5997    /* shl-long/2addr vA, vB */
5998    mov     r3, rINST, lsr #12          @ r3<- B
5999    ubfx    r9, rINST, #8, #4           @ r9<- A
6000    GET_VREG(r2, r3)                    @ r2<- vB
6001    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6002    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6003    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6004
6005    mov     r1, r1, asl r2              @  r1<- r1 << r2
6006    rsb     r3, r2, #32                 @  r3<- 32 - r2
6007    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6008    subs    ip, r2, #32                 @  ip<- r2 - 32
6009    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6010    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6011    mov     r0, r0, asl r2              @  r0<- r0 << r2
6012    b       .LOP_SHL_LONG_2ADDR_finish
6013
6014/* ------------------------------ */
6015    .balign 64
6016.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6017/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
6018    /*
6019     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6020     * 32-bit shift distance.
6021     */
6022    /* shr-long/2addr vA, vB */
6023    mov     r3, rINST, lsr #12          @ r3<- B
6024    ubfx    r9, rINST, #8, #4           @ r9<- A
6025    GET_VREG(r2, r3)                    @ r2<- vB
6026    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6027    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6028    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6029
6030    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6031    rsb     r3, r2, #32                 @  r3<- 32 - r2
6032    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6033    subs    ip, r2, #32                 @  ip<- r2 - 32
6034    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6035    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6036    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6037    b       .LOP_SHR_LONG_2ADDR_finish
6038
6039/* ------------------------------ */
6040    .balign 64
6041.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6042/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6043    /*
6044     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6045     * 32-bit shift distance.
6046     */
6047    /* ushr-long/2addr vA, vB */
6048    mov     r3, rINST, lsr #12          @ r3<- B
6049    ubfx    r9, rINST, #8, #4           @ r9<- A
6050    GET_VREG(r2, r3)                    @ r2<- vB
6051    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6052    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6053    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6054
6055    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6056    rsb     r3, r2, #32                 @  r3<- 32 - r2
6057    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6058    subs    ip, r2, #32                 @  ip<- r2 - 32
6059    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6060    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6061    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6062    b       .LOP_USHR_LONG_2ADDR_finish
6063
6064/* ------------------------------ */
6065    .balign 64
6066.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6067/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6068/* File: arm-vfp/fbinop2addr.S */
6069    /*
6070     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6071     * an "instr" line that specifies an instruction that performs
6072     * "s2 = s0 op s1".
6073     *
6074     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6075     */
6076    /* binop/2addr vA, vB */
6077    mov     r3, rINST, lsr #12          @ r3<- B
6078    mov     r9, rINST, lsr #8           @ r9<- A+
6079    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6080    and     r9, r9, #15                 @ r9<- A
6081    flds    s1, [r3]                    @ s1<- vB
6082    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6083    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6084    flds    s0, [r9]                    @ s0<- vA
6085
6086    fadds   s2, s0, s1                              @ s2<- op
6087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6088    fsts    s2, [r9]                    @ vAA<- s2
6089    GOTO_OPCODE(ip)                     @ jump to next instruction
6090
6091
6092/* ------------------------------ */
6093    .balign 64
6094.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6095/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6096/* File: arm-vfp/fbinop2addr.S */
6097    /*
6098     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6099     * an "instr" line that specifies an instruction that performs
6100     * "s2 = s0 op s1".
6101     *
6102     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6103     */
6104    /* binop/2addr vA, vB */
6105    mov     r3, rINST, lsr #12          @ r3<- B
6106    mov     r9, rINST, lsr #8           @ r9<- A+
6107    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6108    and     r9, r9, #15                 @ r9<- A
6109    flds    s1, [r3]                    @ s1<- vB
6110    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6111    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6112    flds    s0, [r9]                    @ s0<- vA
6113
6114    fsubs   s2, s0, s1                              @ s2<- op
6115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6116    fsts    s2, [r9]                    @ vAA<- s2
6117    GOTO_OPCODE(ip)                     @ jump to next instruction
6118
6119
6120/* ------------------------------ */
6121    .balign 64
6122.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6123/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6124/* File: arm-vfp/fbinop2addr.S */
6125    /*
6126     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6127     * an "instr" line that specifies an instruction that performs
6128     * "s2 = s0 op s1".
6129     *
6130     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6131     */
6132    /* binop/2addr vA, vB */
6133    mov     r3, rINST, lsr #12          @ r3<- B
6134    mov     r9, rINST, lsr #8           @ r9<- A+
6135    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6136    and     r9, r9, #15                 @ r9<- A
6137    flds    s1, [r3]                    @ s1<- vB
6138    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6139    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6140    flds    s0, [r9]                    @ s0<- vA
6141
6142    fmuls   s2, s0, s1                              @ s2<- op
6143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6144    fsts    s2, [r9]                    @ vAA<- s2
6145    GOTO_OPCODE(ip)                     @ jump to next instruction
6146
6147
6148/* ------------------------------ */
6149    .balign 64
6150.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6151/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6152/* File: arm-vfp/fbinop2addr.S */
6153    /*
6154     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6155     * an "instr" line that specifies an instruction that performs
6156     * "s2 = s0 op s1".
6157     *
6158     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6159     */
6160    /* binop/2addr vA, vB */
6161    mov     r3, rINST, lsr #12          @ r3<- B
6162    mov     r9, rINST, lsr #8           @ r9<- A+
6163    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6164    and     r9, r9, #15                 @ r9<- A
6165    flds    s1, [r3]                    @ s1<- vB
6166    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6167    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6168    flds    s0, [r9]                    @ s0<- vA
6169
6170    fdivs   s2, s0, s1                              @ s2<- op
6171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6172    fsts    s2, [r9]                    @ vAA<- s2
6173    GOTO_OPCODE(ip)                     @ jump to next instruction
6174
6175
6176/* ------------------------------ */
6177    .balign 64
6178.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6179/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6180/* EABI doesn't define a float remainder function, but libm does */
6181/* File: armv6t2/binop2addr.S */
6182    /*
6183     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6184     * that specifies an instruction that performs "result = r0 op r1".
6185     * This could be an ARM instruction or a function call.  (If the result
6186     * comes back in a register other than r0, you can override "result".)
6187     *
6188     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6189     * vCC (r1).  Useful for integer division and modulus.
6190     *
6191     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6192     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6193     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6194     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6195     */
6196    /* binop/2addr vA, vB */
6197    mov     r3, rINST, lsr #12          @ r3<- B
6198    ubfx    r9, rINST, #8, #4           @ r9<- A
6199    GET_VREG(r1, r3)                    @ r1<- vB
6200    GET_VREG(r0, r9)                    @ r0<- vA
6201    .if 0
6202    cmp     r1, #0                      @ is second operand zero?
6203    beq     common_errDivideByZero
6204    .endif
6205    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6206
6207                               @ optional op; may set condition codes
6208    bl      fmodf                              @ r0<- op, r0-r3 changed
6209    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6210    SET_VREG(r0, r9)               @ vAA<- r0
6211    GOTO_OPCODE(ip)                     @ jump to next instruction
6212    /* 10-13 instructions */
6213
6214
6215/* ------------------------------ */
6216    .balign 64
6217.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6218/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6219/* File: arm-vfp/fbinopWide2addr.S */
6220    /*
6221     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6222     * an "instr" line that specifies an instruction that performs
6223     * "d2 = d0 op d1".
6224     *
6225     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6226     *      div-double/2addr
6227     */
6228    /* binop/2addr vA, vB */
6229    mov     r3, rINST, lsr #12          @ r3<- B
6230    mov     r9, rINST, lsr #8           @ r9<- A+
6231    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6232    and     r9, r9, #15                 @ r9<- A
6233    fldd    d1, [r3]                    @ d1<- vB
6234    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6235    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6236    fldd    d0, [r9]                    @ d0<- vA
6237
6238    faddd   d2, d0, d1                              @ d2<- op
6239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6240    fstd    d2, [r9]                    @ vAA<- d2
6241    GOTO_OPCODE(ip)                     @ jump to next instruction
6242
6243
6244/* ------------------------------ */
6245    .balign 64
6246.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6247/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6248/* File: arm-vfp/fbinopWide2addr.S */
6249    /*
6250     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6251     * an "instr" line that specifies an instruction that performs
6252     * "d2 = d0 op d1".
6253     *
6254     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6255     *      div-double/2addr
6256     */
6257    /* binop/2addr vA, vB */
6258    mov     r3, rINST, lsr #12          @ r3<- B
6259    mov     r9, rINST, lsr #8           @ r9<- A+
6260    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6261    and     r9, r9, #15                 @ r9<- A
6262    fldd    d1, [r3]                    @ d1<- vB
6263    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6264    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6265    fldd    d0, [r9]                    @ d0<- vA
6266
6267    fsubd   d2, d0, d1                              @ d2<- op
6268    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6269    fstd    d2, [r9]                    @ vAA<- d2
6270    GOTO_OPCODE(ip)                     @ jump to next instruction
6271
6272
6273/* ------------------------------ */
6274    .balign 64
6275.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6276/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6277/* File: arm-vfp/fbinopWide2addr.S */
6278    /*
6279     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6280     * an "instr" line that specifies an instruction that performs
6281     * "d2 = d0 op d1".
6282     *
6283     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6284     *      div-double/2addr
6285     */
6286    /* binop/2addr vA, vB */
6287    mov     r3, rINST, lsr #12          @ r3<- B
6288    mov     r9, rINST, lsr #8           @ r9<- A+
6289    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6290    and     r9, r9, #15                 @ r9<- A
6291    fldd    d1, [r3]                    @ d1<- vB
6292    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6293    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6294    fldd    d0, [r9]                    @ d0<- vA
6295
6296    fmuld   d2, d0, d1                              @ d2<- op
6297    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6298    fstd    d2, [r9]                    @ vAA<- d2
6299    GOTO_OPCODE(ip)                     @ jump to next instruction
6300
6301
6302/* ------------------------------ */
6303    .balign 64
6304.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6305/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6306/* File: arm-vfp/fbinopWide2addr.S */
6307    /*
6308     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6309     * an "instr" line that specifies an instruction that performs
6310     * "d2 = d0 op d1".
6311     *
6312     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6313     *      div-double/2addr
6314     */
6315    /* binop/2addr vA, vB */
6316    mov     r3, rINST, lsr #12          @ r3<- B
6317    mov     r9, rINST, lsr #8           @ r9<- A+
6318    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6319    and     r9, r9, #15                 @ r9<- A
6320    fldd    d1, [r3]                    @ d1<- vB
6321    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6322    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6323    fldd    d0, [r9]                    @ d0<- vA
6324
6325    fdivd   d2, d0, d1                              @ d2<- op
6326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6327    fstd    d2, [r9]                    @ vAA<- d2
6328    GOTO_OPCODE(ip)                     @ jump to next instruction
6329
6330
6331/* ------------------------------ */
6332    .balign 64
6333.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6334/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6335/* EABI doesn't define a double remainder function, but libm does */
6336/* File: armv6t2/binopWide2addr.S */
6337    /*
6338     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6339     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6340     * This could be an ARM instruction or a function call.  (If the result
6341     * comes back in a register other than r0, you can override "result".)
6342     *
6343     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6344     * vCC (r1).  Useful for integer division and modulus.
6345     *
6346     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6347     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6348     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6349     *      rem-double/2addr
6350     */
6351    /* binop/2addr vA, vB */
6352    mov     r1, rINST, lsr #12          @ r1<- B
6353    ubfx    r9, rINST, #8, #4           @ r9<- A
6354    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6355    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6356    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6357    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6358    .if 0
6359    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6360    beq     common_errDivideByZero
6361    .endif
6362    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6363
6364                               @ optional op; may set condition codes
6365    bl      fmod                              @ result<- op, r0-r3 changed
6366    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6367    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6368    GOTO_OPCODE(ip)                     @ jump to next instruction
6369    /* 12-15 instructions */
6370
6371
6372/* ------------------------------ */
6373    .balign 64
6374.L_OP_ADD_INT_LIT16: /* 0xd0 */
6375/* File: armv6t2/OP_ADD_INT_LIT16.S */
6376/* File: armv6t2/binopLit16.S */
6377    /*
6378     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6379     * that specifies an instruction that performs "result = r0 op r1".
6380     * This could be an ARM instruction or a function call.  (If the result
6381     * comes back in a register other than r0, you can override "result".)
6382     *
6383     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6384     * vCC (r1).  Useful for integer division and modulus.
6385     *
6386     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6387     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6388     */
6389    /* binop/lit16 vA, vB, #+CCCC */
6390    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6391    mov     r2, rINST, lsr #12          @ r2<- B
6392    ubfx    r9, rINST, #8, #4           @ r9<- A
6393    GET_VREG(r0, r2)                    @ r0<- vB
6394    .if 0
6395    cmp     r1, #0                      @ is second operand zero?
6396    beq     common_errDivideByZero
6397    .endif
6398    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6399
6400    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6401    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6402    SET_VREG(r0, r9)               @ vAA<- r0
6403    GOTO_OPCODE(ip)                     @ jump to next instruction
6404    /* 10-13 instructions */
6405
6406
6407/* ------------------------------ */
6408    .balign 64
6409.L_OP_RSUB_INT: /* 0xd1 */
6410/* File: armv6t2/OP_RSUB_INT.S */
6411/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6412/* File: armv6t2/binopLit16.S */
6413    /*
6414     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6415     * that specifies an instruction that performs "result = r0 op r1".
6416     * This could be an ARM instruction or a function call.  (If the result
6417     * comes back in a register other than r0, you can override "result".)
6418     *
6419     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6420     * vCC (r1).  Useful for integer division and modulus.
6421     *
6422     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6423     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6424     */
6425    /* binop/lit16 vA, vB, #+CCCC */
6426    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6427    mov     r2, rINST, lsr #12          @ r2<- B
6428    ubfx    r9, rINST, #8, #4           @ r9<- A
6429    GET_VREG(r0, r2)                    @ r0<- vB
6430    .if 0
6431    cmp     r1, #0                      @ is second operand zero?
6432    beq     common_errDivideByZero
6433    .endif
6434    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6435
6436    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6438    SET_VREG(r0, r9)               @ vAA<- r0
6439    GOTO_OPCODE(ip)                     @ jump to next instruction
6440    /* 10-13 instructions */
6441
6442
6443/* ------------------------------ */
6444    .balign 64
6445.L_OP_MUL_INT_LIT16: /* 0xd2 */
6446/* File: armv6t2/OP_MUL_INT_LIT16.S */
6447/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6448/* File: armv6t2/binopLit16.S */
6449    /*
6450     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6451     * that specifies an instruction that performs "result = r0 op r1".
6452     * This could be an ARM instruction or a function call.  (If the result
6453     * comes back in a register other than r0, you can override "result".)
6454     *
6455     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6456     * vCC (r1).  Useful for integer division and modulus.
6457     *
6458     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6459     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6460     */
6461    /* binop/lit16 vA, vB, #+CCCC */
6462    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6463    mov     r2, rINST, lsr #12          @ r2<- B
6464    ubfx    r9, rINST, #8, #4           @ r9<- A
6465    GET_VREG(r0, r2)                    @ r0<- vB
6466    .if 0
6467    cmp     r1, #0                      @ is second operand zero?
6468    beq     common_errDivideByZero
6469    .endif
6470    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6471
6472    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6473    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6474    SET_VREG(r0, r9)               @ vAA<- r0
6475    GOTO_OPCODE(ip)                     @ jump to next instruction
6476    /* 10-13 instructions */
6477
6478
6479/* ------------------------------ */
6480    .balign 64
6481.L_OP_DIV_INT_LIT16: /* 0xd3 */
6482/* File: armv6t2/OP_DIV_INT_LIT16.S */
6483/* File: armv6t2/binopLit16.S */
6484    /*
6485     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6486     * that specifies an instruction that performs "result = r0 op r1".
6487     * This could be an ARM instruction or a function call.  (If the result
6488     * comes back in a register other than r0, you can override "result".)
6489     *
6490     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6491     * vCC (r1).  Useful for integer division and modulus.
6492     *
6493     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6494     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6495     */
6496    /* binop/lit16 vA, vB, #+CCCC */
6497    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6498    mov     r2, rINST, lsr #12          @ r2<- B
6499    ubfx    r9, rINST, #8, #4           @ r9<- A
6500    GET_VREG(r0, r2)                    @ r0<- vB
6501    .if 1
6502    cmp     r1, #0                      @ is second operand zero?
6503    beq     common_errDivideByZero
6504    .endif
6505    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6506
6507    bl     __aeabi_idiv                              @ 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_REM_INT_LIT16: /* 0xd4 */
6517/* File: armv6t2/OP_REM_INT_LIT16.S */
6518/* idivmod returns quotient in r0 and remainder in r1 */
6519/* File: armv6t2/binopLit16.S */
6520    /*
6521     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6522     * that specifies an instruction that performs "result = r0 op r1".
6523     * This could be an ARM instruction or a function call.  (If the result
6524     * comes back in a register other than r0, you can override "result".)
6525     *
6526     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6527     * vCC (r1).  Useful for integer division and modulus.
6528     *
6529     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6530     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6531     */
6532    /* binop/lit16 vA, vB, #+CCCC */
6533    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6534    mov     r2, rINST, lsr #12          @ r2<- B
6535    ubfx    r9, rINST, #8, #4           @ r9<- A
6536    GET_VREG(r0, r2)                    @ r0<- vB
6537    .if 1
6538    cmp     r1, #0                      @ is second operand zero?
6539    beq     common_errDivideByZero
6540    .endif
6541    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6542
6543    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6544    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6545    SET_VREG(r1, r9)               @ vAA<- r1
6546    GOTO_OPCODE(ip)                     @ jump to next instruction
6547    /* 10-13 instructions */
6548
6549
6550/* ------------------------------ */
6551    .balign 64
6552.L_OP_AND_INT_LIT16: /* 0xd5 */
6553/* File: armv6t2/OP_AND_INT_LIT16.S */
6554/* File: armv6t2/binopLit16.S */
6555    /*
6556     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6557     * that specifies an instruction that performs "result = r0 op r1".
6558     * This could be an ARM instruction or a function call.  (If the result
6559     * comes back in a register other than r0, you can override "result".)
6560     *
6561     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6562     * vCC (r1).  Useful for integer division and modulus.
6563     *
6564     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6565     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6566     */
6567    /* binop/lit16 vA, vB, #+CCCC */
6568    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6569    mov     r2, rINST, lsr #12          @ r2<- B
6570    ubfx    r9, rINST, #8, #4           @ r9<- A
6571    GET_VREG(r0, r2)                    @ r0<- vB
6572    .if 0
6573    cmp     r1, #0                      @ is second operand zero?
6574    beq     common_errDivideByZero
6575    .endif
6576    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6577
6578    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6580    SET_VREG(r0, r9)               @ vAA<- r0
6581    GOTO_OPCODE(ip)                     @ jump to next instruction
6582    /* 10-13 instructions */
6583
6584
6585/* ------------------------------ */
6586    .balign 64
6587.L_OP_OR_INT_LIT16: /* 0xd6 */
6588/* File: armv6t2/OP_OR_INT_LIT16.S */
6589/* File: armv6t2/binopLit16.S */
6590    /*
6591     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6592     * that specifies an instruction that performs "result = r0 op r1".
6593     * This could be an ARM instruction or a function call.  (If the result
6594     * comes back in a register other than r0, you can override "result".)
6595     *
6596     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6597     * vCC (r1).  Useful for integer division and modulus.
6598     *
6599     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6600     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6601     */
6602    /* binop/lit16 vA, vB, #+CCCC */
6603    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6604    mov     r2, rINST, lsr #12          @ r2<- B
6605    ubfx    r9, rINST, #8, #4           @ r9<- A
6606    GET_VREG(r0, r2)                    @ r0<- vB
6607    .if 0
6608    cmp     r1, #0                      @ is second operand zero?
6609    beq     common_errDivideByZero
6610    .endif
6611    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6612
6613    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6614    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6615    SET_VREG(r0, r9)               @ vAA<- r0
6616    GOTO_OPCODE(ip)                     @ jump to next instruction
6617    /* 10-13 instructions */
6618
6619
6620/* ------------------------------ */
6621    .balign 64
6622.L_OP_XOR_INT_LIT16: /* 0xd7 */
6623/* File: armv6t2/OP_XOR_INT_LIT16.S */
6624/* File: armv6t2/binopLit16.S */
6625    /*
6626     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6627     * that specifies an instruction that performs "result = r0 op r1".
6628     * This could be an ARM instruction or a function call.  (If the result
6629     * comes back in a register other than r0, you can override "result".)
6630     *
6631     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6632     * vCC (r1).  Useful for integer division and modulus.
6633     *
6634     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6635     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6636     */
6637    /* binop/lit16 vA, vB, #+CCCC */
6638    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6639    mov     r2, rINST, lsr #12          @ r2<- B
6640    ubfx    r9, rINST, #8, #4           @ r9<- A
6641    GET_VREG(r0, r2)                    @ r0<- vB
6642    .if 0
6643    cmp     r1, #0                      @ is second operand zero?
6644    beq     common_errDivideByZero
6645    .endif
6646    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6647
6648    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6650    SET_VREG(r0, r9)               @ vAA<- r0
6651    GOTO_OPCODE(ip)                     @ jump to next instruction
6652    /* 10-13 instructions */
6653
6654
6655/* ------------------------------ */
6656    .balign 64
6657.L_OP_ADD_INT_LIT8: /* 0xd8 */
6658/* File: armv5te/OP_ADD_INT_LIT8.S */
6659/* File: armv5te/binopLit8.S */
6660    /*
6661     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6662     * that specifies an instruction that performs "result = r0 op r1".
6663     * This could be an ARM instruction or a function call.  (If the result
6664     * comes back in a register other than r0, you can override "result".)
6665     *
6666     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6667     * vCC (r1).  Useful for integer division and modulus.
6668     *
6669     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6670     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6671     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6672     */
6673    /* binop/lit8 vAA, vBB, #+CC */
6674    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6675    mov     r9, rINST, lsr #8           @ r9<- AA
6676    and     r2, r3, #255                @ r2<- BB
6677    GET_VREG(r0, r2)                    @ r0<- vBB
6678    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6679    .if 0
6680    @cmp     r1, #0                      @ is second operand zero?
6681    beq     common_errDivideByZero
6682    .endif
6683    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6684
6685                               @ optional op; may set condition codes
6686    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6687    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6688    SET_VREG(r0, r9)               @ vAA<- r0
6689    GOTO_OPCODE(ip)                     @ jump to next instruction
6690    /* 10-12 instructions */
6691
6692
6693/* ------------------------------ */
6694    .balign 64
6695.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6696/* File: armv5te/OP_RSUB_INT_LIT8.S */
6697/* File: armv5te/binopLit8.S */
6698    /*
6699     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6700     * that specifies an instruction that performs "result = r0 op r1".
6701     * This could be an ARM instruction or a function call.  (If the result
6702     * comes back in a register other than r0, you can override "result".)
6703     *
6704     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6705     * vCC (r1).  Useful for integer division and modulus.
6706     *
6707     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6708     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6709     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6710     */
6711    /* binop/lit8 vAA, vBB, #+CC */
6712    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6713    mov     r9, rINST, lsr #8           @ r9<- AA
6714    and     r2, r3, #255                @ r2<- BB
6715    GET_VREG(r0, r2)                    @ r0<- vBB
6716    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6717    .if 0
6718    @cmp     r1, #0                      @ is second operand zero?
6719    beq     common_errDivideByZero
6720    .endif
6721    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6722
6723                               @ optional op; may set condition codes
6724    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6725    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6726    SET_VREG(r0, r9)               @ vAA<- r0
6727    GOTO_OPCODE(ip)                     @ jump to next instruction
6728    /* 10-12 instructions */
6729
6730
6731/* ------------------------------ */
6732    .balign 64
6733.L_OP_MUL_INT_LIT8: /* 0xda */
6734/* File: armv5te/OP_MUL_INT_LIT8.S */
6735/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6736/* File: armv5te/binopLit8.S */
6737    /*
6738     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6739     * that specifies an instruction that performs "result = r0 op r1".
6740     * This could be an ARM instruction or a function call.  (If the result
6741     * comes back in a register other than r0, you can override "result".)
6742     *
6743     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6744     * vCC (r1).  Useful for integer division and modulus.
6745     *
6746     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6747     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6748     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6749     */
6750    /* binop/lit8 vAA, vBB, #+CC */
6751    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6752    mov     r9, rINST, lsr #8           @ r9<- AA
6753    and     r2, r3, #255                @ r2<- BB
6754    GET_VREG(r0, r2)                    @ r0<- vBB
6755    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6756    .if 0
6757    @cmp     r1, #0                      @ is second operand zero?
6758    beq     common_errDivideByZero
6759    .endif
6760    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6761
6762                               @ optional op; may set condition codes
6763    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6764    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6765    SET_VREG(r0, r9)               @ vAA<- r0
6766    GOTO_OPCODE(ip)                     @ jump to next instruction
6767    /* 10-12 instructions */
6768
6769
6770/* ------------------------------ */
6771    .balign 64
6772.L_OP_DIV_INT_LIT8: /* 0xdb */
6773/* File: armv5te/OP_DIV_INT_LIT8.S */
6774/* File: armv5te/binopLit8.S */
6775    /*
6776     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6777     * that specifies an instruction that performs "result = r0 op r1".
6778     * This could be an ARM instruction or a function call.  (If the result
6779     * comes back in a register other than r0, you can override "result".)
6780     *
6781     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6782     * vCC (r1).  Useful for integer division and modulus.
6783     *
6784     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6785     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6786     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6787     */
6788    /* binop/lit8 vAA, vBB, #+CC */
6789    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6790    mov     r9, rINST, lsr #8           @ r9<- AA
6791    and     r2, r3, #255                @ r2<- BB
6792    GET_VREG(r0, r2)                    @ r0<- vBB
6793    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6794    .if 1
6795    @cmp     r1, #0                      @ is second operand zero?
6796    beq     common_errDivideByZero
6797    .endif
6798    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6799
6800                               @ optional op; may set condition codes
6801    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6803    SET_VREG(r0, r9)               @ vAA<- r0
6804    GOTO_OPCODE(ip)                     @ jump to next instruction
6805    /* 10-12 instructions */
6806
6807
6808/* ------------------------------ */
6809    .balign 64
6810.L_OP_REM_INT_LIT8: /* 0xdc */
6811/* File: armv5te/OP_REM_INT_LIT8.S */
6812/* idivmod returns quotient in r0 and remainder in r1 */
6813/* File: armv5te/binopLit8.S */
6814    /*
6815     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6816     * that specifies an instruction that performs "result = r0 op r1".
6817     * This could be an ARM instruction or a function call.  (If the result
6818     * comes back in a register other than r0, you can override "result".)
6819     *
6820     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6821     * vCC (r1).  Useful for integer division and modulus.
6822     *
6823     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6824     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6825     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6826     */
6827    /* binop/lit8 vAA, vBB, #+CC */
6828    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6829    mov     r9, rINST, lsr #8           @ r9<- AA
6830    and     r2, r3, #255                @ r2<- BB
6831    GET_VREG(r0, r2)                    @ r0<- vBB
6832    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6833    .if 1
6834    @cmp     r1, #0                      @ is second operand zero?
6835    beq     common_errDivideByZero
6836    .endif
6837    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6838
6839                               @ optional op; may set condition codes
6840    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6842    SET_VREG(r1, r9)               @ vAA<- r1
6843    GOTO_OPCODE(ip)                     @ jump to next instruction
6844    /* 10-12 instructions */
6845
6846
6847/* ------------------------------ */
6848    .balign 64
6849.L_OP_AND_INT_LIT8: /* 0xdd */
6850/* File: armv5te/OP_AND_INT_LIT8.S */
6851/* File: armv5te/binopLit8.S */
6852    /*
6853     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6854     * that specifies an instruction that performs "result = r0 op r1".
6855     * This could be an ARM instruction or a function call.  (If the result
6856     * comes back in a register other than r0, you can override "result".)
6857     *
6858     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6859     * vCC (r1).  Useful for integer division and modulus.
6860     *
6861     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6862     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6863     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6864     */
6865    /* binop/lit8 vAA, vBB, #+CC */
6866    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6867    mov     r9, rINST, lsr #8           @ r9<- AA
6868    and     r2, r3, #255                @ r2<- BB
6869    GET_VREG(r0, r2)                    @ r0<- vBB
6870    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6871    .if 0
6872    @cmp     r1, #0                      @ is second operand zero?
6873    beq     common_errDivideByZero
6874    .endif
6875    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6876
6877                               @ optional op; may set condition codes
6878    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6879    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6880    SET_VREG(r0, r9)               @ vAA<- r0
6881    GOTO_OPCODE(ip)                     @ jump to next instruction
6882    /* 10-12 instructions */
6883
6884
6885/* ------------------------------ */
6886    .balign 64
6887.L_OP_OR_INT_LIT8: /* 0xde */
6888/* File: armv5te/OP_OR_INT_LIT8.S */
6889/* File: armv5te/binopLit8.S */
6890    /*
6891     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6892     * that specifies an instruction that performs "result = r0 op r1".
6893     * This could be an ARM instruction or a function call.  (If the result
6894     * comes back in a register other than r0, you can override "result".)
6895     *
6896     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6897     * vCC (r1).  Useful for integer division and modulus.
6898     *
6899     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6900     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6901     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6902     */
6903    /* binop/lit8 vAA, vBB, #+CC */
6904    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6905    mov     r9, rINST, lsr #8           @ r9<- AA
6906    and     r2, r3, #255                @ r2<- BB
6907    GET_VREG(r0, r2)                    @ r0<- vBB
6908    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6909    .if 0
6910    @cmp     r1, #0                      @ is second operand zero?
6911    beq     common_errDivideByZero
6912    .endif
6913    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6914
6915                               @ optional op; may set condition codes
6916    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6917    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6918    SET_VREG(r0, r9)               @ vAA<- r0
6919    GOTO_OPCODE(ip)                     @ jump to next instruction
6920    /* 10-12 instructions */
6921
6922
6923/* ------------------------------ */
6924    .balign 64
6925.L_OP_XOR_INT_LIT8: /* 0xdf */
6926/* File: armv5te/OP_XOR_INT_LIT8.S */
6927/* File: armv5te/binopLit8.S */
6928    /*
6929     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6930     * that specifies an instruction that performs "result = r0 op r1".
6931     * This could be an ARM instruction or a function call.  (If the result
6932     * comes back in a register other than r0, you can override "result".)
6933     *
6934     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6935     * vCC (r1).  Useful for integer division and modulus.
6936     *
6937     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6938     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6939     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6940     */
6941    /* binop/lit8 vAA, vBB, #+CC */
6942    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6943    mov     r9, rINST, lsr #8           @ r9<- AA
6944    and     r2, r3, #255                @ r2<- BB
6945    GET_VREG(r0, r2)                    @ r0<- vBB
6946    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6947    .if 0
6948    @cmp     r1, #0                      @ is second operand zero?
6949    beq     common_errDivideByZero
6950    .endif
6951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6952
6953                               @ optional op; may set condition codes
6954    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6955    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6956    SET_VREG(r0, r9)               @ vAA<- r0
6957    GOTO_OPCODE(ip)                     @ jump to next instruction
6958    /* 10-12 instructions */
6959
6960
6961/* ------------------------------ */
6962    .balign 64
6963.L_OP_SHL_INT_LIT8: /* 0xe0 */
6964/* File: armv5te/OP_SHL_INT_LIT8.S */
6965/* File: armv5te/binopLit8.S */
6966    /*
6967     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6968     * that specifies an instruction that performs "result = r0 op r1".
6969     * This could be an ARM instruction or a function call.  (If the result
6970     * comes back in a register other than r0, you can override "result".)
6971     *
6972     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6973     * vCC (r1).  Useful for integer division and modulus.
6974     *
6975     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6976     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6977     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6978     */
6979    /* binop/lit8 vAA, vBB, #+CC */
6980    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6981    mov     r9, rINST, lsr #8           @ r9<- AA
6982    and     r2, r3, #255                @ r2<- BB
6983    GET_VREG(r0, r2)                    @ r0<- vBB
6984    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6985    .if 0
6986    @cmp     r1, #0                      @ is second operand zero?
6987    beq     common_errDivideByZero
6988    .endif
6989    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6990
6991    and     r1, r1, #31                           @ optional op; may set condition codes
6992    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
6993    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6994    SET_VREG(r0, r9)               @ vAA<- r0
6995    GOTO_OPCODE(ip)                     @ jump to next instruction
6996    /* 10-12 instructions */
6997
6998
6999/* ------------------------------ */
7000    .balign 64
7001.L_OP_SHR_INT_LIT8: /* 0xe1 */
7002/* File: armv5te/OP_SHR_INT_LIT8.S */
7003/* File: armv5te/binopLit8.S */
7004    /*
7005     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7006     * that specifies an instruction that performs "result = r0 op r1".
7007     * This could be an ARM instruction or a function call.  (If the result
7008     * comes back in a register other than r0, you can override "result".)
7009     *
7010     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7011     * vCC (r1).  Useful for integer division and modulus.
7012     *
7013     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7014     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7015     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7016     */
7017    /* binop/lit8 vAA, vBB, #+CC */
7018    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7019    mov     r9, rINST, lsr #8           @ r9<- AA
7020    and     r2, r3, #255                @ r2<- BB
7021    GET_VREG(r0, r2)                    @ r0<- vBB
7022    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7023    .if 0
7024    @cmp     r1, #0                      @ is second operand zero?
7025    beq     common_errDivideByZero
7026    .endif
7027    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7028
7029    and     r1, r1, #31                           @ optional op; may set condition codes
7030    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7031    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7032    SET_VREG(r0, r9)               @ vAA<- r0
7033    GOTO_OPCODE(ip)                     @ jump to next instruction
7034    /* 10-12 instructions */
7035
7036
7037/* ------------------------------ */
7038    .balign 64
7039.L_OP_USHR_INT_LIT8: /* 0xe2 */
7040/* File: armv5te/OP_USHR_INT_LIT8.S */
7041/* File: armv5te/binopLit8.S */
7042    /*
7043     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7044     * that specifies an instruction that performs "result = r0 op r1".
7045     * This could be an ARM instruction or a function call.  (If the result
7046     * comes back in a register other than r0, you can override "result".)
7047     *
7048     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7049     * vCC (r1).  Useful for integer division and modulus.
7050     *
7051     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7052     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7053     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7054     */
7055    /* binop/lit8 vAA, vBB, #+CC */
7056    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7057    mov     r9, rINST, lsr #8           @ r9<- AA
7058    and     r2, r3, #255                @ r2<- BB
7059    GET_VREG(r0, r2)                    @ r0<- vBB
7060    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7061    .if 0
7062    @cmp     r1, #0                      @ is second operand zero?
7063    beq     common_errDivideByZero
7064    .endif
7065    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7066
7067    and     r1, r1, #31                           @ optional op; may set condition codes
7068    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7070    SET_VREG(r0, r9)               @ vAA<- r0
7071    GOTO_OPCODE(ip)                     @ jump to next instruction
7072    /* 10-12 instructions */
7073
7074
7075/* ------------------------------ */
7076    .balign 64
7077.L_OP_IGET_VOLATILE: /* 0xe3 */
7078/* File: armv5te/OP_IGET_VOLATILE.S */
7079/* File: armv5te/OP_IGET.S */
7080    /*
7081     * General 32-bit instance field get.
7082     *
7083     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7084     */
7085    /* op vA, vB, field@CCCC */
7086    mov     r0, rINST, lsr #12          @ r0<- B
7087    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7088    FETCH(r1, 1)                        @ r1<- field ref CCCC
7089    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7090    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7091    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7092    cmp     r0, #0                      @ is resolved entry null?
7093    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
70948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7095    EXPORT_PC()                         @ resolve() could throw
7096    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7097    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7098    cmp     r0, #0
7099    bne     .LOP_IGET_VOLATILE_finish
7100    b       common_exceptionThrown
7101
7102
7103/* ------------------------------ */
7104    .balign 64
7105.L_OP_IPUT_VOLATILE: /* 0xe4 */
7106/* File: armv5te/OP_IPUT_VOLATILE.S */
7107/* File: armv5te/OP_IPUT.S */
7108    /*
7109     * General 32-bit instance field put.
7110     *
7111     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7112     */
7113    /* op vA, vB, field@CCCC */
7114    mov     r0, rINST, lsr #12          @ r0<- B
7115    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7116    FETCH(r1, 1)                        @ r1<- field ref CCCC
7117    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7118    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7119    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7120    cmp     r0, #0                      @ is resolved entry null?
7121    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71228:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7123    EXPORT_PC()                         @ resolve() could throw
7124    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7125    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7126    cmp     r0, #0                      @ success?
7127    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7128    b       common_exceptionThrown
7129
7130
7131/* ------------------------------ */
7132    .balign 64
7133.L_OP_SGET_VOLATILE: /* 0xe5 */
7134/* File: armv5te/OP_SGET_VOLATILE.S */
7135/* File: armv5te/OP_SGET.S */
7136    /*
7137     * General 32-bit SGET handler.
7138     *
7139     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7140     */
7141    /* op vAA, field@BBBB */
7142    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7143    FETCH(r1, 1)                        @ r1<- field ref BBBB
7144    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7145    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7146    cmp     r0, #0                      @ is resolved entry null?
7147    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7148.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7149    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7150    SMP_DMB                            @ acquiring load
7151    mov     r2, rINST, lsr #8           @ r2<- AA
7152    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7153    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7155    GOTO_OPCODE(ip)                     @ jump to next instruction
7156
7157
7158/* ------------------------------ */
7159    .balign 64
7160.L_OP_SPUT_VOLATILE: /* 0xe6 */
7161/* File: armv5te/OP_SPUT_VOLATILE.S */
7162/* File: armv5te/OP_SPUT.S */
7163    /*
7164     * General 32-bit SPUT handler.
7165     *
7166     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7167     */
7168    /* op vAA, field@BBBB */
7169    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7170    FETCH(r1, 1)                        @ r1<- field ref BBBB
7171    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7172    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7173    cmp     r0, #0                      @ is resolved entry null?
7174    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7175.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7176    mov     r2, rINST, lsr #8           @ r2<- AA
7177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7178    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7180    SMP_DMB                            @ releasing store
7181    str     r1, [r0, #offStaticField_value] @ field<- vAA
7182    GOTO_OPCODE(ip)                     @ jump to next instruction
7183
7184
7185/* ------------------------------ */
7186    .balign 64
7187.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7188/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7189/* File: armv5te/OP_IGET.S */
7190    /*
7191     * General 32-bit instance field get.
7192     *
7193     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7194     */
7195    /* op vA, vB, field@CCCC */
7196    mov     r0, rINST, lsr #12          @ r0<- B
7197    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7198    FETCH(r1, 1)                        @ r1<- field ref CCCC
7199    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7200    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7201    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7202    cmp     r0, #0                      @ is resolved entry null?
7203    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
72048:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7205    EXPORT_PC()                         @ resolve() could throw
7206    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7207    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7208    cmp     r0, #0
7209    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7210    b       common_exceptionThrown
7211
7212
7213/* ------------------------------ */
7214    .balign 64
7215.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7216/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7217/* File: armv5te/OP_IGET_WIDE.S */
7218    /*
7219     * Wide 32-bit instance field get.
7220     */
7221    /* iget-wide vA, vB, field@CCCC */
7222    mov     r0, rINST, lsr #12          @ r0<- B
7223    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7224    FETCH(r1, 1)                        @ r1<- field ref CCCC
7225    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7226    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7227    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7228    cmp     r0, #0                      @ is resolved entry null?
7229    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72308:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7231    EXPORT_PC()                         @ resolve() could throw
7232    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7233    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7234    cmp     r0, #0
7235    bne     .LOP_IGET_WIDE_VOLATILE_finish
7236    b       common_exceptionThrown
7237
7238
7239/* ------------------------------ */
7240    .balign 64
7241.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7242/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7243/* File: armv5te/OP_IPUT_WIDE.S */
7244    /* iput-wide vA, vB, field@CCCC */
7245    mov     r0, rINST, lsr #12          @ r0<- B
7246    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7247    FETCH(r1, 1)                        @ r1<- field ref CCCC
7248    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7249    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7250    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7251    cmp     r0, #0                      @ is resolved entry null?
7252    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72538:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7254    EXPORT_PC()                         @ resolve() could throw
7255    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7256    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7257    cmp     r0, #0                      @ success?
7258    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7259    b       common_exceptionThrown
7260
7261
7262/* ------------------------------ */
7263    .balign 64
7264.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7265/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7266/* File: armv5te/OP_SGET_WIDE.S */
7267    /*
7268     * 64-bit SGET handler.
7269     */
7270    /* sget-wide vAA, field@BBBB */
7271    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7272    FETCH(r1, 1)                        @ r1<- field ref BBBB
7273    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7274    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7275    cmp     r0, #0                      @ is resolved entry null?
7276    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7277.LOP_SGET_WIDE_VOLATILE_finish:
7278    mov     r9, rINST, lsr #8           @ r9<- AA
7279    .if 1
7280    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7281    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7282    .else
7283    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7284    .endif
7285    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7286    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7287    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7288    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7289    GOTO_OPCODE(ip)                     @ jump to next instruction
7290
7291
7292/* ------------------------------ */
7293    .balign 64
7294.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7295/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7296/* File: armv5te/OP_SPUT_WIDE.S */
7297    /*
7298     * 64-bit SPUT handler.
7299     */
7300    /* sput-wide vAA, field@BBBB */
7301    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7302    FETCH(r1, 1)                        @ r1<- field ref BBBB
7303    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7304    mov     r9, rINST, lsr #8           @ r9<- AA
7305    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7306    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7307    cmp     r2, #0                      @ is resolved entry null?
7308    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7309.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7310    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7311    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7312    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7313    .if 1
7314    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7315    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7316    .else
7317    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7318    .endif
7319    GOTO_OPCODE(r10)                    @ jump to next instruction
7320
7321
7322/* ------------------------------ */
7323    .balign 64
7324.L_OP_BREAKPOINT: /* 0xec */
7325/* File: armv5te/OP_BREAKPOINT.S */
7326/* File: armv5te/unused.S */
7327    bl      common_abort
7328
7329
7330/* ------------------------------ */
7331    .balign 64
7332.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7333/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7334    /*
7335     * Handle a throw-verification-error instruction.  This throws an
7336     * exception for an error discovered during verification.  The
7337     * exception is indicated by AA, with some detail provided by BBBB.
7338     */
7339    /* op AA, ref@BBBB */
7340    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7341    FETCH(r2, 1)                        @ r2<- BBBB
7342    EXPORT_PC()                         @ export the PC
7343    mov     r1, rINST, lsr #8           @ r1<- AA
7344    bl      dvmThrowVerificationError   @ always throws
7345    b       common_exceptionThrown      @ handle exception
7346
7347/* ------------------------------ */
7348    .balign 64
7349.L_OP_EXECUTE_INLINE: /* 0xee */
7350/* File: armv5te/OP_EXECUTE_INLINE.S */
7351    /*
7352     * Execute a "native inline" instruction.
7353     *
7354     * We need to call an InlineOp4Func:
7355     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7356     *
7357     * The first four args are in r0-r3, pointer to return value storage
7358     * is on the stack.  The function's return value is a flag that tells
7359     * us if an exception was thrown.
7360     */
7361    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7362    FETCH(r10, 1)                       @ r10<- BBBB
7363    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7364    EXPORT_PC()                         @ can throw
7365    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7366    mov     r0, rINST, lsr #12          @ r0<- B
7367    str     r1, [sp]                    @ push &glue->retval
7368    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7369    add     sp, sp, #8                  @ pop stack
7370    cmp     r0, #0                      @ test boolean result of inline
7371    beq     common_exceptionThrown      @ returned false, handle exception
7372    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7373    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7374    GOTO_OPCODE(ip)                     @ jump to next instruction
7375
7376/* ------------------------------ */
7377    .balign 64
7378.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7379/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7380    /*
7381     * Execute a "native inline" instruction, using "/range" semantics.
7382     * Same idea as execute-inline, but we get the args differently.
7383     *
7384     * We need to call an InlineOp4Func:
7385     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7386     *
7387     * The first four args are in r0-r3, pointer to return value storage
7388     * is on the stack.  The function's return value is a flag that tells
7389     * us if an exception was thrown.
7390     */
7391    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7392    FETCH(r10, 1)                       @ r10<- BBBB
7393    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7394    EXPORT_PC()                         @ can throw
7395    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7396    mov     r0, rINST, lsr #8           @ r0<- AA
7397    str     r1, [sp]                    @ push &glue->retval
7398    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7399    add     sp, sp, #8                  @ pop stack
7400    cmp     r0, #0                      @ test boolean result of inline
7401    beq     common_exceptionThrown      @ returned false, handle exception
7402    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7403    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7404    GOTO_OPCODE(ip)                     @ jump to next instruction
7405
7406/* ------------------------------ */
7407    .balign 64
7408.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7409/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7410    /*
7411     * invoke-direct-empty is a no-op in a "standard" interpreter.
7412     */
7413    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7414    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7415    GOTO_OPCODE(ip)                     @ execute it
7416
7417/* ------------------------------ */
7418    .balign 64
7419.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7420/* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7421    SMP_DMB_ST
7422    b       common_returnFromMethod
7423
7424/* ------------------------------ */
7425    .balign 64
7426.L_OP_IGET_QUICK: /* 0xf2 */
7427/* File: armv6t2/OP_IGET_QUICK.S */
7428    /* For: iget-quick, iget-object-quick */
7429    /* op vA, vB, offset@CCCC */
7430    mov     r2, rINST, lsr #12          @ r2<- B
7431    FETCH(r1, 1)                        @ r1<- field byte offset
7432    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7433    ubfx    r2, rINST, #8, #4           @ r2<- A
7434    cmp     r3, #0                      @ check object for null
7435    beq     common_errNullObject        @ object was null
7436    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7438    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7439    SET_VREG(r0, r2)                    @ fp[A]<- r0
7440    GOTO_OPCODE(ip)                     @ jump to next instruction
7441
7442/* ------------------------------ */
7443    .balign 64
7444.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7445/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7446    /* iget-wide-quick vA, vB, offset@CCCC */
7447    mov     r2, rINST, lsr #12          @ r2<- B
7448    FETCH(ip, 1)                        @ ip<- field byte offset
7449    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7450    ubfx    r2, rINST, #8, #4           @ r2<- A
7451    cmp     r3, #0                      @ check object for null
7452    beq     common_errNullObject        @ object was null
7453    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7455    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7456    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7457    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7458    GOTO_OPCODE(ip)                     @ jump to next instruction
7459
7460/* ------------------------------ */
7461    .balign 64
7462.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7463/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7464/* File: armv5te/OP_IGET_QUICK.S */
7465    /* For: iget-quick, iget-object-quick */
7466    /* op vA, vB, offset@CCCC */
7467    mov     r2, rINST, lsr #12          @ r2<- B
7468    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7469    FETCH(r1, 1)                        @ r1<- field byte offset
7470    cmp     r3, #0                      @ check object for null
7471    mov     r2, rINST, lsr #8           @ r2<- A(+)
7472    beq     common_errNullObject        @ object was null
7473    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7474    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7475    and     r2, r2, #15
7476    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7477    SET_VREG(r0, r2)                    @ fp[A]<- r0
7478    GOTO_OPCODE(ip)                     @ jump to next instruction
7479
7480
7481/* ------------------------------ */
7482    .balign 64
7483.L_OP_IPUT_QUICK: /* 0xf5 */
7484/* File: armv6t2/OP_IPUT_QUICK.S */
7485    /* For: iput-quick, iput-object-quick */
7486    /* op vA, vB, offset@CCCC */
7487    mov     r2, rINST, lsr #12          @ r2<- B
7488    FETCH(r1, 1)                        @ r1<- field byte offset
7489    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7490    ubfx    r2, rINST, #8, #4           @ r2<- A
7491    cmp     r3, #0                      @ check object for null
7492    beq     common_errNullObject        @ object was null
7493    GET_VREG(r0, r2)                    @ r0<- fp[A]
7494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7495    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7496    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7497    GOTO_OPCODE(ip)                     @ jump to next instruction
7498
7499/* ------------------------------ */
7500    .balign 64
7501.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7502/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7503    /* iput-wide-quick vA, vB, offset@CCCC */
7504    mov     r1, rINST, lsr #12          @ r1<- B
7505    ubfx    r0, rINST, #8, #4           @ r0<- A
7506    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7507    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7508    cmp     r2, #0                      @ check object for null
7509    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7510    beq     common_errNullObject        @ object was null
7511    FETCH(r3, 1)                        @ r3<- field byte offset
7512    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7513    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7514    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7515    GOTO_OPCODE(ip)                     @ jump to next instruction
7516
7517/* ------------------------------ */
7518    .balign 64
7519.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7520/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7521    /* For: iput-object-quick */
7522    /* op vA, vB, offset@CCCC */
7523    mov     r2, rINST, lsr #12          @ r2<- B
7524    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7525    FETCH(r1, 1)                        @ r1<- field byte offset
7526    cmp     r3, #0                      @ check object for null
7527    mov     r2, rINST, lsr #8           @ r2<- A(+)
7528    beq     common_errNullObject        @ object was null
7529    and     r2, r2, #15
7530    GET_VREG(r0, r2)                    @ r0<- fp[A]
7531    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7532    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7533    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7534    cmp     r0, #0
7535    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7537    GOTO_OPCODE(ip)                     @ jump to next instruction
7538
7539/* ------------------------------ */
7540    .balign 64
7541.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7542/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7543    /*
7544     * Handle an optimized virtual method call.
7545     *
7546     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7547     */
7548    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7549    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7550    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7551    FETCH(r1, 1)                        @ r1<- BBBB
7552    .if     (!0)
7553    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7554    .endif
7555    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7556    cmp     r2, #0                      @ is "this" null?
7557    beq     common_errNullObject        @ null "this", throw exception
7558    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7559    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7560    EXPORT_PC()                         @ invoke must export
7561    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7562    bl      common_invokeMethodNoRange @ continue on
7563
7564/* ------------------------------ */
7565    .balign 64
7566.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7567/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7568/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7569    /*
7570     * Handle an optimized virtual method call.
7571     *
7572     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7573     */
7574    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7575    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7576    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7577    FETCH(r1, 1)                        @ r1<- BBBB
7578    .if     (!1)
7579    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7580    .endif
7581    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7582    cmp     r2, #0                      @ is "this" null?
7583    beq     common_errNullObject        @ null "this", throw exception
7584    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7585    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7586    EXPORT_PC()                         @ invoke must export
7587    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7588    bl      common_invokeMethodRange @ continue on
7589
7590
7591/* ------------------------------ */
7592    .balign 64
7593.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7594/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7595    /*
7596     * Handle an optimized "super" method call.
7597     *
7598     * for: [opt] invoke-super-quick, invoke-super-quick/range
7599     */
7600    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7601    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7602    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7603    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7604    .if     (!0)
7605    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7606    .endif
7607    FETCH(r1, 1)                        @ r1<- BBBB
7608    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7609    EXPORT_PC()                         @ must export for invoke
7610    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7611    GET_VREG(r3, r10)                   @ r3<- "this"
7612    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7613    cmp     r3, #0                      @ null "this" ref?
7614    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7615    beq     common_errNullObject        @ "this" is null, throw exception
7616    bl      common_invokeMethodNoRange @ continue on
7617
7618/* ------------------------------ */
7619    .balign 64
7620.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7621/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7622/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7623    /*
7624     * Handle an optimized "super" method call.
7625     *
7626     * for: [opt] invoke-super-quick, invoke-super-quick/range
7627     */
7628    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7629    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7630    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7631    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7632    .if     (!1)
7633    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7634    .endif
7635    FETCH(r1, 1)                        @ r1<- BBBB
7636    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7637    EXPORT_PC()                         @ must export for invoke
7638    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7639    GET_VREG(r3, r10)                   @ r3<- "this"
7640    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7641    cmp     r3, #0                      @ null "this" ref?
7642    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7643    beq     common_errNullObject        @ "this" is null, throw exception
7644    bl      common_invokeMethodRange @ continue on
7645
7646
7647/* ------------------------------ */
7648    .balign 64
7649.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7650/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7651/* File: armv5te/OP_IPUT_OBJECT.S */
7652    /*
7653     * 32-bit instance field put.
7654     *
7655     * for: iput-object, iput-object-volatile
7656     */
7657    /* op vA, vB, field@CCCC */
7658    mov     r0, rINST, lsr #12          @ r0<- B
7659    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7660    FETCH(r1, 1)                        @ r1<- field ref CCCC
7661    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7662    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7663    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7664    cmp     r0, #0                      @ is resolved entry null?
7665    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76668:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7667    EXPORT_PC()                         @ resolve() could throw
7668    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7669    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7670    cmp     r0, #0                      @ success?
7671    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7672    b       common_exceptionThrown
7673
7674
7675/* ------------------------------ */
7676    .balign 64
7677.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7678/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7679/* File: armv5te/OP_SGET.S */
7680    /*
7681     * General 32-bit SGET handler.
7682     *
7683     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7684     */
7685    /* op vAA, field@BBBB */
7686    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7687    FETCH(r1, 1)                        @ r1<- field ref BBBB
7688    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7689    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7690    cmp     r0, #0                      @ is resolved entry null?
7691    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7692.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7693    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7694    SMP_DMB                            @ acquiring load
7695    mov     r2, rINST, lsr #8           @ r2<- AA
7696    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7697    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7698    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7699    GOTO_OPCODE(ip)                     @ jump to next instruction
7700
7701
7702/* ------------------------------ */
7703    .balign 64
7704.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7705/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7706/* File: armv5te/OP_SPUT_OBJECT.S */
7707    /*
7708     * 32-bit SPUT handler for objects
7709     *
7710     * for: sput-object, sput-object-volatile
7711     */
7712    /* op vAA, field@BBBB */
7713    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7714    FETCH(r1, 1)                        @ r1<- field ref BBBB
7715    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7716    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7717    cmp     r0, #0                      @ is resolved entry null?
7718    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7719    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7720    EXPORT_PC()                         @ resolve() could throw, so export now
7721    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7722    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7723    cmp     r0, #0                      @ success?
7724    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7725    b       common_exceptionThrown      @ no, handle exception
7726
7727
7728
7729/* ------------------------------ */
7730    .balign 64
7731.L_OP_UNUSED_FF: /* 0xff */
7732/* File: armv5te/OP_UNUSED_FF.S */
7733/* File: armv5te/unused.S */
7734    bl      common_abort
7735
7736
7737
7738    .balign 64
7739    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7740    .global dvmAsmInstructionEnd
7741dvmAsmInstructionEnd:
7742
7743/*
7744 * ===========================================================================
7745 *  Sister implementations
7746 * ===========================================================================
7747 */
7748    .global dvmAsmSisterStart
7749    .type   dvmAsmSisterStart, %function
7750    .text
7751    .balign 4
7752dvmAsmSisterStart:
7753
7754/* continuation for OP_CONST_STRING */
7755
7756    /*
7757     * Continuation if the String has not yet been resolved.
7758     *  r1: BBBB (String ref)
7759     *  r9: target register
7760     */
7761.LOP_CONST_STRING_resolve:
7762    EXPORT_PC()
7763    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7764    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7765    bl      dvmResolveString            @ r0<- String reference
7766    cmp     r0, #0                      @ failed?
7767    beq     common_exceptionThrown      @ yup, handle the exception
7768    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7770    SET_VREG(r0, r9)                    @ vAA<- r0
7771    GOTO_OPCODE(ip)                     @ jump to next instruction
7772
7773/* continuation for OP_CONST_STRING_JUMBO */
7774
7775    /*
7776     * Continuation if the String has not yet been resolved.
7777     *  r1: BBBBBBBB (String ref)
7778     *  r9: target register
7779     */
7780.LOP_CONST_STRING_JUMBO_resolve:
7781    EXPORT_PC()
7782    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7783    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7784    bl      dvmResolveString            @ r0<- String reference
7785    cmp     r0, #0                      @ failed?
7786    beq     common_exceptionThrown      @ yup, handle the exception
7787    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7788    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7789    SET_VREG(r0, r9)                    @ vAA<- r0
7790    GOTO_OPCODE(ip)                     @ jump to next instruction
7791
7792/* continuation for OP_CONST_CLASS */
7793
7794    /*
7795     * Continuation if the Class has not yet been resolved.
7796     *  r1: BBBB (Class ref)
7797     *  r9: target register
7798     */
7799.LOP_CONST_CLASS_resolve:
7800    EXPORT_PC()
7801    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7802    mov     r2, #1                      @ r2<- true
7803    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7804    bl      dvmResolveClass             @ r0<- Class reference
7805    cmp     r0, #0                      @ failed?
7806    beq     common_exceptionThrown      @ yup, handle the exception
7807    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7809    SET_VREG(r0, r9)                    @ vAA<- r0
7810    GOTO_OPCODE(ip)                     @ jump to next instruction
7811
7812/* continuation for OP_CHECK_CAST */
7813
7814    /*
7815     * Trivial test failed, need to perform full check.  This is common.
7816     *  r0 holds obj->clazz
7817     *  r1 holds class resolved from BBBB
7818     *  r9 holds object
7819     */
7820.LOP_CHECK_CAST_fullcheck:
7821    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7822    cmp     r0, #0                      @ failed?
7823    bne     .LOP_CHECK_CAST_okay            @ no, success
7824
7825    @ A cast has failed.  We need to throw a ClassCastException with the
7826    @ class of the object that failed to be cast.
7827    EXPORT_PC()                         @ about to throw
7828    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7829    ldr     r0, .LstrClassCastExceptionPtr
7830    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7831    bl      dvmThrowExceptionWithClassMessage
7832    b       common_exceptionThrown
7833
7834    /*
7835     * Resolution required.  This is the least-likely path.
7836     *
7837     *  r2 holds BBBB
7838     *  r9 holds object
7839     */
7840.LOP_CHECK_CAST_resolve:
7841    EXPORT_PC()                         @ resolve() could throw
7842    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7843    mov     r1, r2                      @ r1<- BBBB
7844    mov     r2, #0                      @ r2<- false
7845    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7846    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7847    cmp     r0, #0                      @ got null?
7848    beq     common_exceptionThrown      @ yes, handle exception
7849    mov     r1, r0                      @ r1<- class resolved from BBB
7850    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7851    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7852
7853.LstrClassCastExceptionPtr:
7854    .word   .LstrClassCastException
7855
7856/* continuation for OP_INSTANCE_OF */
7857
7858    /*
7859     * Trivial test failed, need to perform full check.  This is common.
7860     *  r0 holds obj->clazz
7861     *  r1 holds class resolved from BBBB
7862     *  r9 holds A
7863     */
7864.LOP_INSTANCE_OF_fullcheck:
7865    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7866    @ fall through to OP_INSTANCE_OF_store
7867
7868    /*
7869     * r0 holds boolean result
7870     * r9 holds A
7871     */
7872.LOP_INSTANCE_OF_store:
7873    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7874    SET_VREG(r0, r9)                    @ vA<- r0
7875    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7876    GOTO_OPCODE(ip)                     @ jump to next instruction
7877
7878    /*
7879     * Trivial test succeeded, save and bail.
7880     *  r9 holds A
7881     */
7882.LOP_INSTANCE_OF_trivial:
7883    mov     r0, #1                      @ indicate success
7884    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7885    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7886    SET_VREG(r0, r9)                    @ vA<- r0
7887    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7888    GOTO_OPCODE(ip)                     @ jump to next instruction
7889
7890    /*
7891     * Resolution required.  This is the least-likely path.
7892     *
7893     *  r3 holds BBBB
7894     *  r9 holds A
7895     */
7896.LOP_INSTANCE_OF_resolve:
7897    EXPORT_PC()                         @ resolve() could throw
7898    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7899    mov     r1, r3                      @ r1<- BBBB
7900    mov     r2, #1                      @ r2<- true
7901    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7902    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7903    cmp     r0, #0                      @ got null?
7904    beq     common_exceptionThrown      @ yes, handle exception
7905    mov     r1, r0                      @ r1<- class resolved from BBB
7906    mov     r3, rINST, lsr #12          @ r3<- B
7907    GET_VREG(r0, r3)                    @ r0<- vB (object)
7908    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7909    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7910
7911/* continuation for OP_NEW_INSTANCE */
7912
7913    .balign 32                          @ minimize cache lines
7914.LOP_NEW_INSTANCE_finish: @ r0=new object
7915    mov     r3, rINST, lsr #8           @ r3<- AA
7916    cmp     r0, #0                      @ failed?
7917    beq     common_exceptionThrown      @ yes, handle the exception
7918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7920    SET_VREG(r0, r3)                    @ vAA<- r0
7921    GOTO_OPCODE(ip)                     @ jump to next instruction
7922
7923    /*
7924     * Class initialization required.
7925     *
7926     *  r0 holds class object
7927     */
7928.LOP_NEW_INSTANCE_needinit:
7929    mov     r9, r0                      @ save r0
7930    bl      dvmInitClass                @ initialize class
7931    cmp     r0, #0                      @ check boolean result
7932    mov     r0, r9                      @ restore r0
7933    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7934    b       common_exceptionThrown      @ failed, deal with init exception
7935
7936    /*
7937     * Resolution required.  This is the least-likely path.
7938     *
7939     *  r1 holds BBBB
7940     */
7941.LOP_NEW_INSTANCE_resolve:
7942    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7943    mov     r2, #0                      @ r2<- false
7944    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7945    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7946    cmp     r0, #0                      @ got null?
7947    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7948    b       common_exceptionThrown      @ yes, handle exception
7949
7950.LstrInstantiationErrorPtr:
7951    .word   .LstrInstantiationError
7952
7953/* continuation for OP_NEW_ARRAY */
7954
7955
7956    /*
7957     * Resolve class.  (This is an uncommon case.)
7958     *
7959     *  r1 holds array length
7960     *  r2 holds class ref CCCC
7961     */
7962.LOP_NEW_ARRAY_resolve:
7963    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7964    mov     r9, r1                      @ r9<- length (save)
7965    mov     r1, r2                      @ r1<- CCCC
7966    mov     r2, #0                      @ r2<- false
7967    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7968    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7969    cmp     r0, #0                      @ got null?
7970    mov     r1, r9                      @ r1<- length (restore)
7971    beq     common_exceptionThrown      @ yes, handle exception
7972    @ fall through to OP_NEW_ARRAY_finish
7973
7974    /*
7975     * Finish allocation.
7976     *
7977     *  r0 holds class
7978     *  r1 holds array length
7979     */
7980.LOP_NEW_ARRAY_finish:
7981    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7982    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7983    cmp     r0, #0                      @ failed?
7984    mov     r2, rINST, lsr #8           @ r2<- A+
7985    beq     common_exceptionThrown      @ yes, handle the exception
7986    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7987    and     r2, r2, #15                 @ r2<- A
7988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7989    SET_VREG(r0, r2)                    @ vA<- r0
7990    GOTO_OPCODE(ip)                     @ jump to next instruction
7991
7992/* continuation for OP_FILLED_NEW_ARRAY */
7993
7994    /*
7995     * On entry:
7996     *  r0 holds array class
7997     *  r10 holds AA or BA
7998     */
7999.LOP_FILLED_NEW_ARRAY_continue:
8000    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8001    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8002    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8003    .if     0
8004    mov     r1, r10                     @ r1<- AA (length)
8005    .else
8006    mov     r1, r10, lsr #4             @ r1<- B (length)
8007    .endif
8008    cmp     rINST, #'I'                 @ array of ints?
8009    cmpne   rINST, #'L'                 @ array of objects?
8010    cmpne   rINST, #'['                 @ array of arrays?
8011    mov     r9, r1                      @ save length in r9
8012    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8013    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8014    cmp     r0, #0                      @ null return?
8015    beq     common_exceptionThrown      @ alloc failed, handle exception
8016
8017    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8018    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8019    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8020    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8021    subs    r9, r9, #1                  @ length--, check for neg
8022    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8023    bmi     2f                          @ was zero, bail
8024
8025    @ copy values from registers into the array
8026    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8027    .if     0
8028    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80291:  ldr     r3, [r2], #4                @ r3<- *r2++
8030    subs    r9, r9, #1                  @ count--
8031    str     r3, [r0], #4                @ *contents++ = vX
8032    bpl     1b
8033    @ continue at 2
8034    .else
8035    cmp     r9, #4                      @ length was initially 5?
8036    and     r2, r10, #15                @ r2<- A
8037    bne     1f                          @ <= 4 args, branch
8038    GET_VREG(r3, r2)                    @ r3<- vA
8039    sub     r9, r9, #1                  @ count--
8040    str     r3, [r0, #16]               @ contents[4] = vA
80411:  and     r2, r1, #15                 @ r2<- F/E/D/C
8042    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8043    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8044    subs    r9, r9, #1                  @ count--
8045    str     r3, [r0], #4                @ *contents++ = vX
8046    bpl     1b
8047    @ continue at 2
8048    .endif
8049
80502:
8051    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8052    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8053    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8054    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8055    cmp     r1, #'I'                         @ Is int array?
8056    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8057    GOTO_OPCODE(ip)                          @ execute it
8058
8059    /*
8060     * Throw an exception indicating that we have not implemented this
8061     * mode of filled-new-array.
8062     */
8063.LOP_FILLED_NEW_ARRAY_notimpl:
8064    ldr     r0, .L_strInternalError
8065    ldr     r1, .L_strFilledNewArrayNotImpl
8066    bl      dvmThrowException
8067    b       common_exceptionThrown
8068
8069    .if     (!0)                 @ define in one or the other, not both
8070.L_strFilledNewArrayNotImpl:
8071    .word   .LstrFilledNewArrayNotImpl
8072.L_strInternalError:
8073    .word   .LstrInternalError
8074    .endif
8075
8076/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8077
8078    /*
8079     * On entry:
8080     *  r0 holds array class
8081     *  r10 holds AA or BA
8082     */
8083.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8084    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8085    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8086    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8087    .if     1
8088    mov     r1, r10                     @ r1<- AA (length)
8089    .else
8090    mov     r1, r10, lsr #4             @ r1<- B (length)
8091    .endif
8092    cmp     rINST, #'I'                 @ array of ints?
8093    cmpne   rINST, #'L'                 @ array of objects?
8094    cmpne   rINST, #'['                 @ array of arrays?
8095    mov     r9, r1                      @ save length in r9
8096    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8097    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8098    cmp     r0, #0                      @ null return?
8099    beq     common_exceptionThrown      @ alloc failed, handle exception
8100
8101    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8102    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8103    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8104    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8105    subs    r9, r9, #1                  @ length--, check for neg
8106    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8107    bmi     2f                          @ was zero, bail
8108
8109    @ copy values from registers into the array
8110    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8111    .if     1
8112    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81131:  ldr     r3, [r2], #4                @ r3<- *r2++
8114    subs    r9, r9, #1                  @ count--
8115    str     r3, [r0], #4                @ *contents++ = vX
8116    bpl     1b
8117    @ continue at 2
8118    .else
8119    cmp     r9, #4                      @ length was initially 5?
8120    and     r2, r10, #15                @ r2<- A
8121    bne     1f                          @ <= 4 args, branch
8122    GET_VREG(r3, r2)                    @ r3<- vA
8123    sub     r9, r9, #1                  @ count--
8124    str     r3, [r0, #16]               @ contents[4] = vA
81251:  and     r2, r1, #15                 @ r2<- F/E/D/C
8126    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8127    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8128    subs    r9, r9, #1                  @ count--
8129    str     r3, [r0], #4                @ *contents++ = vX
8130    bpl     1b
8131    @ continue at 2
8132    .endif
8133
81342:
8135    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8136    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8137    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8138    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8139    cmp     r1, #'I'                         @ Is int array?
8140    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8141    GOTO_OPCODE(ip)                          @ execute it
8142
8143    /*
8144     * Throw an exception indicating that we have not implemented this
8145     * mode of filled-new-array.
8146     */
8147.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8148    ldr     r0, .L_strInternalError
8149    ldr     r1, .L_strFilledNewArrayNotImpl
8150    bl      dvmThrowException
8151    b       common_exceptionThrown
8152
8153    .if     (!1)                 @ define in one or the other, not both
8154.L_strFilledNewArrayNotImpl:
8155    .word   .LstrFilledNewArrayNotImpl
8156.L_strInternalError:
8157    .word   .LstrInternalError
8158    .endif
8159
8160/* continuation for OP_CMPL_FLOAT */
8161.LOP_CMPL_FLOAT_finish:
8162    SET_VREG(r0, r9)                    @ vAA<- r0
8163    GOTO_OPCODE(ip)                     @ jump to next instruction
8164
8165/* continuation for OP_CMPG_FLOAT */
8166.LOP_CMPG_FLOAT_finish:
8167    SET_VREG(r0, r9)                    @ vAA<- r0
8168    GOTO_OPCODE(ip)                     @ jump to next instruction
8169
8170/* continuation for OP_CMPL_DOUBLE */
8171.LOP_CMPL_DOUBLE_finish:
8172    SET_VREG(r0, r9)                    @ vAA<- r0
8173    GOTO_OPCODE(ip)                     @ jump to next instruction
8174
8175/* continuation for OP_CMPG_DOUBLE */
8176.LOP_CMPG_DOUBLE_finish:
8177    SET_VREG(r0, r9)                    @ vAA<- r0
8178    GOTO_OPCODE(ip)                     @ jump to next instruction
8179
8180/* continuation for OP_CMP_LONG */
8181
8182.LOP_CMP_LONG_less:
8183    mvn     r1, #0                      @ r1<- -1
8184    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8185    @ instead, we just replicate the tail end.
8186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8187    SET_VREG(r1, r9)                    @ vAA<- r1
8188    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8189    GOTO_OPCODE(ip)                     @ jump to next instruction
8190
8191.LOP_CMP_LONG_greater:
8192    mov     r1, #1                      @ r1<- 1
8193    @ fall through to _finish
8194
8195.LOP_CMP_LONG_finish:
8196    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8197    SET_VREG(r1, r9)                    @ vAA<- r1
8198    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8199    GOTO_OPCODE(ip)                     @ jump to next instruction
8200
8201/* continuation for OP_AGET_WIDE */
8202
8203.LOP_AGET_WIDE_finish:
8204    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8205    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8206    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8208    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8209    GOTO_OPCODE(ip)                     @ jump to next instruction
8210
8211/* continuation for OP_APUT_WIDE */
8212
8213.LOP_APUT_WIDE_finish:
8214    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8215    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8217    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8218    GOTO_OPCODE(ip)                     @ jump to next instruction
8219
8220/* continuation for OP_APUT_OBJECT */
8221    /*
8222     * On entry:
8223     *  rINST = vBB (arrayObj)
8224     *  r9 = vAA (obj)
8225     *  r10 = offset into array (vBB + vCC * width)
8226     */
8227.LOP_APUT_OBJECT_finish:
8228    cmp     r9, #0                      @ storing null reference?
8229    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8230    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8231    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8232    bl      dvmCanPutArrayElement       @ test object type vs. array type
8233    cmp     r0, #0                      @ okay?
8234    beq     common_errArrayStore        @ no
8235    mov     r1, rINST                   @ r1<- arrayObj
8236    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8237    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8238    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8240    str     r9, [r10]                   @ vBB[vCC]<- vAA
8241    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8242    GOTO_OPCODE(ip)                     @ jump to next instruction
8243.LOP_APUT_OBJECT_skip_check:
8244    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8246    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8247    GOTO_OPCODE(ip)                     @ jump to next instruction
8248
8249/* continuation for OP_IGET */
8250
8251    /*
8252     * Currently:
8253     *  r0 holds resolved field
8254     *  r9 holds object
8255     */
8256.LOP_IGET_finish:
8257    @bl      common_squeak0
8258    cmp     r9, #0                      @ check object for null
8259    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8260    beq     common_errNullObject        @ object was null
8261    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8262    ubfx    r2, rINST, #8, #4           @ r2<- A
8263    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8264    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8265    SET_VREG(r0, r2)                    @ fp[A]<- r0
8266    GOTO_OPCODE(ip)                     @ jump to next instruction
8267
8268/* continuation for OP_IGET_WIDE */
8269
8270    /*
8271     * Currently:
8272     *  r0 holds resolved field
8273     *  r9 holds object
8274     */
8275.LOP_IGET_WIDE_finish:
8276    cmp     r9, #0                      @ check object for null
8277    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8278    beq     common_errNullObject        @ object was null
8279    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8280    ubfx    r2, rINST, #8, #4           @ r2<- A
8281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8282    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8284    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8285    GOTO_OPCODE(ip)                     @ jump to next instruction
8286
8287/* continuation for OP_IGET_OBJECT */
8288
8289    /*
8290     * Currently:
8291     *  r0 holds resolved field
8292     *  r9 holds object
8293     */
8294.LOP_IGET_OBJECT_finish:
8295    @bl      common_squeak0
8296    cmp     r9, #0                      @ check object for null
8297    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8298    beq     common_errNullObject        @ object was null
8299    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8300    @ no-op                             @ acquiring load
8301    mov     r2, rINST, lsr #8           @ r2<- A+
8302    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8303    and     r2, r2, #15                 @ r2<- A
8304    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8305    SET_VREG(r0, r2)                    @ fp[A]<- r0
8306    GOTO_OPCODE(ip)                     @ jump to next instruction
8307
8308/* continuation for OP_IGET_BOOLEAN */
8309
8310    /*
8311     * Currently:
8312     *  r0 holds resolved field
8313     *  r9 holds object
8314     */
8315.LOP_IGET_BOOLEAN_finish:
8316    @bl      common_squeak1
8317    cmp     r9, #0                      @ check object for null
8318    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8319    beq     common_errNullObject        @ object was null
8320    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8321    @ no-op                             @ acquiring load
8322    mov     r2, rINST, lsr #8           @ r2<- A+
8323    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8324    and     r2, r2, #15                 @ r2<- A
8325    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8326    SET_VREG(r0, r2)                    @ fp[A]<- r0
8327    GOTO_OPCODE(ip)                     @ jump to next instruction
8328
8329/* continuation for OP_IGET_BYTE */
8330
8331    /*
8332     * Currently:
8333     *  r0 holds resolved field
8334     *  r9 holds object
8335     */
8336.LOP_IGET_BYTE_finish:
8337    @bl      common_squeak2
8338    cmp     r9, #0                      @ check object for null
8339    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8340    beq     common_errNullObject        @ object was null
8341    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8342    @ no-op                             @ acquiring load
8343    mov     r2, rINST, lsr #8           @ r2<- A+
8344    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8345    and     r2, r2, #15                 @ r2<- A
8346    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8347    SET_VREG(r0, r2)                    @ fp[A]<- r0
8348    GOTO_OPCODE(ip)                     @ jump to next instruction
8349
8350/* continuation for OP_IGET_CHAR */
8351
8352    /*
8353     * Currently:
8354     *  r0 holds resolved field
8355     *  r9 holds object
8356     */
8357.LOP_IGET_CHAR_finish:
8358    @bl      common_squeak3
8359    cmp     r9, #0                      @ check object for null
8360    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8361    beq     common_errNullObject        @ object was null
8362    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8363    @ no-op                             @ acquiring load
8364    mov     r2, rINST, lsr #8           @ r2<- A+
8365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8366    and     r2, r2, #15                 @ r2<- A
8367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8368    SET_VREG(r0, r2)                    @ fp[A]<- r0
8369    GOTO_OPCODE(ip)                     @ jump to next instruction
8370
8371/* continuation for OP_IGET_SHORT */
8372
8373    /*
8374     * Currently:
8375     *  r0 holds resolved field
8376     *  r9 holds object
8377     */
8378.LOP_IGET_SHORT_finish:
8379    @bl      common_squeak4
8380    cmp     r9, #0                      @ check object for null
8381    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8382    beq     common_errNullObject        @ object was null
8383    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8384    @ no-op                             @ acquiring load
8385    mov     r2, rINST, lsr #8           @ r2<- A+
8386    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8387    and     r2, r2, #15                 @ r2<- A
8388    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8389    SET_VREG(r0, r2)                    @ fp[A]<- r0
8390    GOTO_OPCODE(ip)                     @ jump to next instruction
8391
8392/* continuation for OP_IPUT */
8393
8394    /*
8395     * Currently:
8396     *  r0 holds resolved field
8397     *  r9 holds object
8398     */
8399.LOP_IPUT_finish:
8400    @bl      common_squeak0
8401    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8402    ubfx    r1, rINST, #8, #4           @ r1<- A
8403    cmp     r9, #0                      @ check object for null
8404    GET_VREG(r0, r1)                    @ r0<- fp[A]
8405    beq     common_errNullObject        @ object was null
8406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8407    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8408    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8409    GOTO_OPCODE(ip)                     @ jump to next instruction
8410
8411/* continuation for OP_IPUT_WIDE */
8412
8413    /*
8414     * Currently:
8415     *  r0 holds resolved field
8416     *  r9 holds object
8417     */
8418.LOP_IPUT_WIDE_finish:
8419    ubfx    r2, rINST, #8, #4           @ r2<- A
8420    cmp     r9, #0                      @ check object for null
8421    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8422    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8423    beq     common_errNullObject        @ object was null
8424    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8425    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8426    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8427    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8428    GOTO_OPCODE(ip)                     @ jump to next instruction
8429
8430/* continuation for OP_IPUT_OBJECT */
8431
8432    /*
8433     * Currently:
8434     *  r0 holds resolved field
8435     *  r9 holds object
8436     */
8437.LOP_IPUT_OBJECT_finish:
8438    @bl      common_squeak0
8439    mov     r1, rINST, lsr #8           @ r1<- A+
8440    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8441    and     r1, r1, #15                 @ r1<- A
8442    cmp     r9, #0                      @ check object for null
8443    GET_VREG(r0, r1)                    @ r0<- fp[A]
8444    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8445    beq     common_errNullObject        @ object was null
8446    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8447    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8448    @ no-op                             @ releasing store
8449    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
8450    cmp     r0, #0                      @ stored a null reference?
8451    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8452    GOTO_OPCODE(ip)                     @ jump to next instruction
8453
8454/* continuation for OP_IPUT_BOOLEAN */
8455
8456    /*
8457     * Currently:
8458     *  r0 holds resolved field
8459     *  r9 holds object
8460     */
8461.LOP_IPUT_BOOLEAN_finish:
8462    @bl      common_squeak1
8463    mov     r1, rINST, lsr #8           @ r1<- A+
8464    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8465    and     r1, r1, #15                 @ r1<- A
8466    cmp     r9, #0                      @ check object for null
8467    GET_VREG(r0, r1)                    @ r0<- fp[A]
8468    beq     common_errNullObject        @ object was null
8469    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8470    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8471    @ no-op                             @ releasing store
8472    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8473    GOTO_OPCODE(ip)                     @ jump to next instruction
8474
8475/* continuation for OP_IPUT_BYTE */
8476
8477    /*
8478     * Currently:
8479     *  r0 holds resolved field
8480     *  r9 holds object
8481     */
8482.LOP_IPUT_BYTE_finish:
8483    @bl      common_squeak2
8484    mov     r1, rINST, lsr #8           @ r1<- A+
8485    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8486    and     r1, r1, #15                 @ r1<- A
8487    cmp     r9, #0                      @ check object for null
8488    GET_VREG(r0, r1)                    @ r0<- fp[A]
8489    beq     common_errNullObject        @ object was null
8490    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8491    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8492    @ no-op                             @ releasing store
8493    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8494    GOTO_OPCODE(ip)                     @ jump to next instruction
8495
8496/* continuation for OP_IPUT_CHAR */
8497
8498    /*
8499     * Currently:
8500     *  r0 holds resolved field
8501     *  r9 holds object
8502     */
8503.LOP_IPUT_CHAR_finish:
8504    @bl      common_squeak3
8505    mov     r1, rINST, lsr #8           @ r1<- A+
8506    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8507    and     r1, r1, #15                 @ r1<- A
8508    cmp     r9, #0                      @ check object for null
8509    GET_VREG(r0, r1)                    @ r0<- fp[A]
8510    beq     common_errNullObject        @ object was null
8511    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8512    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8513    @ no-op                             @ releasing store
8514    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8515    GOTO_OPCODE(ip)                     @ jump to next instruction
8516
8517/* continuation for OP_IPUT_SHORT */
8518
8519    /*
8520     * Currently:
8521     *  r0 holds resolved field
8522     *  r9 holds object
8523     */
8524.LOP_IPUT_SHORT_finish:
8525    @bl      common_squeak4
8526    mov     r1, rINST, lsr #8           @ r1<- A+
8527    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8528    and     r1, r1, #15                 @ r1<- A
8529    cmp     r9, #0                      @ check object for null
8530    GET_VREG(r0, r1)                    @ r0<- fp[A]
8531    beq     common_errNullObject        @ object was null
8532    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8533    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8534    @ no-op                             @ releasing store
8535    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8536    GOTO_OPCODE(ip)                     @ jump to next instruction
8537
8538/* continuation for OP_SGET */
8539
8540    /*
8541     * Continuation if the field has not yet been resolved.
8542     *  r1: BBBB field ref
8543     */
8544.LOP_SGET_resolve:
8545    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8546    EXPORT_PC()                         @ resolve() could throw, so export now
8547    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8548    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8549    cmp     r0, #0                      @ success?
8550    bne     .LOP_SGET_finish          @ yes, finish
8551    b       common_exceptionThrown      @ no, handle exception
8552
8553/* continuation for OP_SGET_WIDE */
8554
8555    /*
8556     * Continuation if the field has not yet been resolved.
8557     *  r1: BBBB field ref
8558     *
8559     * Returns StaticField pointer in r0.
8560     */
8561.LOP_SGET_WIDE_resolve:
8562    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8563    EXPORT_PC()                         @ resolve() could throw, so export now
8564    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8565    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8566    cmp     r0, #0                      @ success?
8567    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8568    b       common_exceptionThrown      @ no, handle exception
8569
8570/* continuation for OP_SGET_OBJECT */
8571
8572    /*
8573     * Continuation if the field has not yet been resolved.
8574     *  r1: BBBB field ref
8575     */
8576.LOP_SGET_OBJECT_resolve:
8577    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8578    EXPORT_PC()                         @ resolve() could throw, so export now
8579    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8580    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8581    cmp     r0, #0                      @ success?
8582    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8583    b       common_exceptionThrown      @ no, handle exception
8584
8585/* continuation for OP_SGET_BOOLEAN */
8586
8587    /*
8588     * Continuation if the field has not yet been resolved.
8589     *  r1: BBBB field ref
8590     */
8591.LOP_SGET_BOOLEAN_resolve:
8592    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8593    EXPORT_PC()                         @ resolve() could throw, so export now
8594    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8595    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8596    cmp     r0, #0                      @ success?
8597    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8598    b       common_exceptionThrown      @ no, handle exception
8599
8600/* continuation for OP_SGET_BYTE */
8601
8602    /*
8603     * Continuation if the field has not yet been resolved.
8604     *  r1: BBBB field ref
8605     */
8606.LOP_SGET_BYTE_resolve:
8607    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8608    EXPORT_PC()                         @ resolve() could throw, so export now
8609    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8610    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8611    cmp     r0, #0                      @ success?
8612    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8613    b       common_exceptionThrown      @ no, handle exception
8614
8615/* continuation for OP_SGET_CHAR */
8616
8617    /*
8618     * Continuation if the field has not yet been resolved.
8619     *  r1: BBBB field ref
8620     */
8621.LOP_SGET_CHAR_resolve:
8622    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8623    EXPORT_PC()                         @ resolve() could throw, so export now
8624    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8625    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8626    cmp     r0, #0                      @ success?
8627    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8628    b       common_exceptionThrown      @ no, handle exception
8629
8630/* continuation for OP_SGET_SHORT */
8631
8632    /*
8633     * Continuation if the field has not yet been resolved.
8634     *  r1: BBBB field ref
8635     */
8636.LOP_SGET_SHORT_resolve:
8637    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8638    EXPORT_PC()                         @ resolve() could throw, so export now
8639    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8640    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8641    cmp     r0, #0                      @ success?
8642    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8643    b       common_exceptionThrown      @ no, handle exception
8644
8645/* continuation for OP_SPUT */
8646
8647    /*
8648     * Continuation if the field has not yet been resolved.
8649     *  r1: BBBB field ref
8650     */
8651.LOP_SPUT_resolve:
8652    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8653    EXPORT_PC()                         @ resolve() could throw, so export now
8654    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8655    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8656    cmp     r0, #0                      @ success?
8657    bne     .LOP_SPUT_finish          @ yes, finish
8658    b       common_exceptionThrown      @ no, handle exception
8659
8660/* continuation for OP_SPUT_WIDE */
8661
8662    /*
8663     * Continuation if the field has not yet been resolved.
8664     *  r1: BBBB field ref
8665     *  r9: &fp[AA]
8666     *
8667     * Returns StaticField pointer in r2.
8668     */
8669.LOP_SPUT_WIDE_resolve:
8670    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8671    EXPORT_PC()                         @ resolve() could throw, so export now
8672    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8673    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8674    cmp     r0, #0                      @ success?
8675    mov     r2, r0                      @ copy to r2
8676    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8677    b       common_exceptionThrown      @ no, handle exception
8678
8679/* continuation for OP_SPUT_OBJECT */
8680.LOP_SPUT_OBJECT_finish:   @ field ptr in r0, method in r9
8681    mov     r2, rINST, lsr #8           @ r2<- AA
8682    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8683    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8684    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8685    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
8686    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8687    add     r0, #offStaticField_value   @ r0<- pointer to store target
8688    @ no-op                             @ releasing store
8689    str     r1, [r0]                    @ field<- vAA
8690    cmp     r1, #0                      @ stored a null object?
8691    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
8692    GOTO_OPCODE(ip)                     @ jump to next instruction
8693
8694/* continuation for OP_SPUT_BOOLEAN */
8695
8696    /*
8697     * Continuation if the field has not yet been resolved.
8698     *  r1: BBBB field ref
8699     */
8700.LOP_SPUT_BOOLEAN_resolve:
8701    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8702    EXPORT_PC()                         @ resolve() could throw, so export now
8703    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8704    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8705    cmp     r0, #0                      @ success?
8706    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8707    b       common_exceptionThrown      @ no, handle exception
8708
8709/* continuation for OP_SPUT_BYTE */
8710
8711    /*
8712     * Continuation if the field has not yet been resolved.
8713     *  r1: BBBB field ref
8714     */
8715.LOP_SPUT_BYTE_resolve:
8716    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8717    EXPORT_PC()                         @ resolve() could throw, so export now
8718    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8719    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8720    cmp     r0, #0                      @ success?
8721    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8722    b       common_exceptionThrown      @ no, handle exception
8723
8724/* continuation for OP_SPUT_CHAR */
8725
8726    /*
8727     * Continuation if the field has not yet been resolved.
8728     *  r1: BBBB field ref
8729     */
8730.LOP_SPUT_CHAR_resolve:
8731    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8732    EXPORT_PC()                         @ resolve() could throw, so export now
8733    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8734    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8735    cmp     r0, #0                      @ success?
8736    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8737    b       common_exceptionThrown      @ no, handle exception
8738
8739/* continuation for OP_SPUT_SHORT */
8740
8741    /*
8742     * Continuation if the field has not yet been resolved.
8743     *  r1: BBBB field ref
8744     */
8745.LOP_SPUT_SHORT_resolve:
8746    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8747    EXPORT_PC()                         @ resolve() could throw, so export now
8748    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8749    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8750    cmp     r0, #0                      @ success?
8751    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8752    b       common_exceptionThrown      @ no, handle exception
8753
8754/* continuation for OP_INVOKE_VIRTUAL */
8755
8756    /*
8757     * At this point:
8758     *  r0 = resolved base method
8759     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8760     */
8761.LOP_INVOKE_VIRTUAL_continue:
8762    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8763    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8764    cmp     r1, #0                      @ is "this" null?
8765    beq     common_errNullObject        @ null "this", throw exception
8766    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8767    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8768    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8769    bl      common_invokeMethodNoRange @ continue on
8770
8771/* continuation for OP_INVOKE_SUPER */
8772
8773    /*
8774     * At this point:
8775     *  r0 = resolved base method
8776     *  r9 = method->clazz
8777     */
8778.LOP_INVOKE_SUPER_continue:
8779    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8780    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8781    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8782    EXPORT_PC()                         @ must export for invoke
8783    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8784    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8785    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8786    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8787    bl      common_invokeMethodNoRange @ continue on
8788
8789.LOP_INVOKE_SUPER_resolve:
8790    mov     r0, r9                      @ r0<- method->clazz
8791    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8792    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8793    cmp     r0, #0                      @ got null?
8794    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8795    b       common_exceptionThrown      @ yes, handle exception
8796
8797    /*
8798     * Throw a NoSuchMethodError with the method name as the message.
8799     *  r0 = resolved base method
8800     */
8801.LOP_INVOKE_SUPER_nsm:
8802    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8803    b       common_errNoSuchMethod
8804
8805/* continuation for OP_INVOKE_DIRECT */
8806
8807    /*
8808     * On entry:
8809     *  r1 = reference (BBBB or CCCC)
8810     *  r10 = "this" register
8811     */
8812.LOP_INVOKE_DIRECT_resolve:
8813    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8814    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8815    mov     r2, #METHOD_DIRECT          @ resolver method type
8816    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8817    cmp     r0, #0                      @ got null?
8818    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8819    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8820    b       common_exceptionThrown      @ yes, handle exception
8821
8822/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8823
8824    /*
8825     * At this point:
8826     *  r0 = resolved base method
8827     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8828     */
8829.LOP_INVOKE_VIRTUAL_RANGE_continue:
8830    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8831    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8832    cmp     r1, #0                      @ is "this" null?
8833    beq     common_errNullObject        @ null "this", throw exception
8834    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8835    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8836    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8837    bl      common_invokeMethodRange @ continue on
8838
8839/* continuation for OP_INVOKE_SUPER_RANGE */
8840
8841    /*
8842     * At this point:
8843     *  r0 = resolved base method
8844     *  r9 = method->clazz
8845     */
8846.LOP_INVOKE_SUPER_RANGE_continue:
8847    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8848    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8849    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8850    EXPORT_PC()                         @ must export for invoke
8851    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8852    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8853    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8854    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8855    bl      common_invokeMethodRange @ continue on
8856
8857.LOP_INVOKE_SUPER_RANGE_resolve:
8858    mov     r0, r9                      @ r0<- method->clazz
8859    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8860    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8861    cmp     r0, #0                      @ got null?
8862    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8863    b       common_exceptionThrown      @ yes, handle exception
8864
8865    /*
8866     * Throw a NoSuchMethodError with the method name as the message.
8867     *  r0 = resolved base method
8868     */
8869.LOP_INVOKE_SUPER_RANGE_nsm:
8870    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8871    b       common_errNoSuchMethod
8872
8873/* continuation for OP_INVOKE_DIRECT_RANGE */
8874
8875    /*
8876     * On entry:
8877     *  r1 = reference (BBBB or CCCC)
8878     *  r10 = "this" register
8879     */
8880.LOP_INVOKE_DIRECT_RANGE_resolve:
8881    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8882    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8883    mov     r2, #METHOD_DIRECT          @ resolver method type
8884    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8885    cmp     r0, #0                      @ got null?
8886    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8887    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8888    b       common_exceptionThrown      @ yes, handle exception
8889
8890/* continuation for OP_FLOAT_TO_LONG */
8891/*
8892 * Convert the float in r0 to a long in r0/r1.
8893 *
8894 * We have to clip values to long min/max per the specification.  The
8895 * expected common case is a "reasonable" value that converts directly
8896 * to modest integer.  The EABI convert function isn't doing this for us.
8897 */
8898f2l_doconv:
8899    stmfd   sp!, {r4, lr}
8900    mov     r1, #0x5f000000             @ (float)maxlong
8901    mov     r4, r0
8902    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8903    cmp     r0, #0                      @ nonzero == yes
8904    mvnne   r0, #0                      @ return maxlong (7fffffff)
8905    mvnne   r1, #0x80000000
8906    ldmnefd sp!, {r4, pc}
8907
8908    mov     r0, r4                      @ recover arg
8909    mov     r1, #0xdf000000             @ (float)minlong
8910    bl      __aeabi_fcmple              @ is arg <= minlong?
8911    cmp     r0, #0                      @ nonzero == yes
8912    movne   r0, #0                      @ return minlong (80000000)
8913    movne   r1, #0x80000000
8914    ldmnefd sp!, {r4, pc}
8915
8916    mov     r0, r4                      @ recover arg
8917    mov     r1, r4
8918    bl      __aeabi_fcmpeq              @ is arg == self?
8919    cmp     r0, #0                      @ zero == no
8920    moveq   r1, #0                      @ return zero for NaN
8921    ldmeqfd sp!, {r4, pc}
8922
8923    mov     r0, r4                      @ recover arg
8924    bl      __aeabi_f2lz                @ convert float to long
8925    ldmfd   sp!, {r4, pc}
8926
8927/* continuation for OP_DOUBLE_TO_LONG */
8928/*
8929 * Convert the double in r0/r1 to a long in r0/r1.
8930 *
8931 * We have to clip values to long min/max per the specification.  The
8932 * expected common case is a "reasonable" value that converts directly
8933 * to modest integer.  The EABI convert function isn't doing this for us.
8934 */
8935d2l_doconv:
8936    stmfd   sp!, {r4, r5, lr}           @ save regs
8937    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8938    add     r3, #0x00e00000             @  0x43e00000
8939    mov     r2, #0                      @ maxlong, as a double (low word)
8940    sub     sp, sp, #4                  @ align for EABI
8941    mov     r4, r0                      @ save a copy of r0
8942    mov     r5, r1                      @  and r1
8943    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8944    cmp     r0, #0                      @ nonzero == yes
8945    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8946    mvnne   r1, #0x80000000
8947    bne     1f
8948
8949    mov     r0, r4                      @ recover arg
8950    mov     r1, r5
8951    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8952    add     r3, #0x00e00000             @  0xc3e00000
8953    mov     r2, #0                      @ minlong, as a double (low word)
8954    bl      __aeabi_dcmple              @ is arg <= minlong?
8955    cmp     r0, #0                      @ nonzero == yes
8956    movne   r0, #0                      @ return minlong (8000000000000000)
8957    movne   r1, #0x80000000
8958    bne     1f
8959
8960    mov     r0, r4                      @ recover arg
8961    mov     r1, r5
8962    mov     r2, r4                      @ compare against self
8963    mov     r3, r5
8964    bl      __aeabi_dcmpeq              @ is arg == self?
8965    cmp     r0, #0                      @ zero == no
8966    moveq   r1, #0                      @ return zero for NaN
8967    beq     1f
8968
8969    mov     r0, r4                      @ recover arg
8970    mov     r1, r5
8971    bl      __aeabi_d2lz                @ convert double to long
8972
89731:
8974    add     sp, sp, #4
8975    ldmfd   sp!, {r4, r5, pc}
8976
8977/* continuation for OP_MUL_LONG */
8978
8979.LOP_MUL_LONG_finish:
8980    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8981    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8982    GOTO_OPCODE(ip)                     @ jump to next instruction
8983
8984/* continuation for OP_SHL_LONG */
8985
8986.LOP_SHL_LONG_finish:
8987    mov     r0, r0, asl r2              @  r0<- r0 << r2
8988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8989    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8990    GOTO_OPCODE(ip)                     @ jump to next instruction
8991
8992/* continuation for OP_SHR_LONG */
8993
8994.LOP_SHR_LONG_finish:
8995    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8996    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8997    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8998    GOTO_OPCODE(ip)                     @ jump to next instruction
8999
9000/* continuation for OP_USHR_LONG */
9001
9002.LOP_USHR_LONG_finish:
9003    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9004    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9005    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9006    GOTO_OPCODE(ip)                     @ jump to next instruction
9007
9008/* continuation for OP_SHL_LONG_2ADDR */
9009
9010.LOP_SHL_LONG_2ADDR_finish:
9011    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9012    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9013    GOTO_OPCODE(ip)                     @ jump to next instruction
9014
9015/* continuation for OP_SHR_LONG_2ADDR */
9016
9017.LOP_SHR_LONG_2ADDR_finish:
9018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9019    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9020    GOTO_OPCODE(ip)                     @ jump to next instruction
9021
9022/* continuation for OP_USHR_LONG_2ADDR */
9023
9024.LOP_USHR_LONG_2ADDR_finish:
9025    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9026    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9027    GOTO_OPCODE(ip)                     @ jump to next instruction
9028
9029/* continuation for OP_IGET_VOLATILE */
9030
9031    /*
9032     * Currently:
9033     *  r0 holds resolved field
9034     *  r9 holds object
9035     */
9036.LOP_IGET_VOLATILE_finish:
9037    @bl      common_squeak0
9038    cmp     r9, #0                      @ check object for null
9039    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9040    beq     common_errNullObject        @ object was null
9041    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9042    SMP_DMB                            @ acquiring load
9043    mov     r2, rINST, lsr #8           @ r2<- A+
9044    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9045    and     r2, r2, #15                 @ r2<- A
9046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9047    SET_VREG(r0, r2)                    @ fp[A]<- r0
9048    GOTO_OPCODE(ip)                     @ jump to next instruction
9049
9050/* continuation for OP_IPUT_VOLATILE */
9051
9052    /*
9053     * Currently:
9054     *  r0 holds resolved field
9055     *  r9 holds object
9056     */
9057.LOP_IPUT_VOLATILE_finish:
9058    @bl      common_squeak0
9059    mov     r1, rINST, lsr #8           @ r1<- A+
9060    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9061    and     r1, r1, #15                 @ r1<- A
9062    cmp     r9, #0                      @ check object for null
9063    GET_VREG(r0, r1)                    @ r0<- fp[A]
9064    beq     common_errNullObject        @ object was null
9065    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9066    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9067    SMP_DMB                            @ releasing store
9068    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9069    GOTO_OPCODE(ip)                     @ jump to next instruction
9070
9071/* continuation for OP_SGET_VOLATILE */
9072
9073    /*
9074     * Continuation if the field has not yet been resolved.
9075     *  r1: BBBB field ref
9076     */
9077.LOP_SGET_VOLATILE_resolve:
9078    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9079    EXPORT_PC()                         @ resolve() could throw, so export now
9080    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9081    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9082    cmp     r0, #0                      @ success?
9083    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9084    b       common_exceptionThrown      @ no, handle exception
9085
9086/* continuation for OP_SPUT_VOLATILE */
9087
9088    /*
9089     * Continuation if the field has not yet been resolved.
9090     *  r1: BBBB field ref
9091     */
9092.LOP_SPUT_VOLATILE_resolve:
9093    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9094    EXPORT_PC()                         @ resolve() could throw, so export now
9095    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9096    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9097    cmp     r0, #0                      @ success?
9098    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9099    b       common_exceptionThrown      @ no, handle exception
9100
9101/* continuation for OP_IGET_OBJECT_VOLATILE */
9102
9103    /*
9104     * Currently:
9105     *  r0 holds resolved field
9106     *  r9 holds object
9107     */
9108.LOP_IGET_OBJECT_VOLATILE_finish:
9109    @bl      common_squeak0
9110    cmp     r9, #0                      @ check object for null
9111    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9112    beq     common_errNullObject        @ object was null
9113    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9114    SMP_DMB                            @ acquiring load
9115    mov     r2, rINST, lsr #8           @ r2<- A+
9116    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9117    and     r2, r2, #15                 @ r2<- A
9118    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9119    SET_VREG(r0, r2)                    @ fp[A]<- r0
9120    GOTO_OPCODE(ip)                     @ jump to next instruction
9121
9122/* continuation for OP_IGET_WIDE_VOLATILE */
9123
9124    /*
9125     * Currently:
9126     *  r0 holds resolved field
9127     *  r9 holds object
9128     */
9129.LOP_IGET_WIDE_VOLATILE_finish:
9130    cmp     r9, #0                      @ check object for null
9131    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9132    beq     common_errNullObject        @ object was null
9133    .if     1
9134    add     r0, r9, r3                  @ r0<- address of field
9135    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9136    .else
9137    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9138    .endif
9139    mov     r2, rINST, lsr #8           @ r2<- A+
9140    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9141    and     r2, r2, #15                 @ r2<- A
9142    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9144    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9145    GOTO_OPCODE(ip)                     @ jump to next instruction
9146
9147/* continuation for OP_IPUT_WIDE_VOLATILE */
9148
9149    /*
9150     * Currently:
9151     *  r0 holds resolved field
9152     *  r9 holds object
9153     */
9154.LOP_IPUT_WIDE_VOLATILE_finish:
9155    mov     r2, rINST, lsr #8           @ r2<- A+
9156    cmp     r9, #0                      @ check object for null
9157    and     r2, r2, #15                 @ r2<- A
9158    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9159    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9160    beq     common_errNullObject        @ object was null
9161    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9162    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9163    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9164    .if     1
9165    add     r2, r9, r3                  @ r2<- target address
9166    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9167    .else
9168    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9169    .endif
9170    GOTO_OPCODE(r10)                    @ jump to next instruction
9171
9172/* continuation for OP_SGET_WIDE_VOLATILE */
9173
9174    /*
9175     * Continuation if the field has not yet been resolved.
9176     *  r1: BBBB field ref
9177     *
9178     * Returns StaticField pointer in r0.
9179     */
9180.LOP_SGET_WIDE_VOLATILE_resolve:
9181    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9182    EXPORT_PC()                         @ resolve() could throw, so export now
9183    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9184    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9185    cmp     r0, #0                      @ success?
9186    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9187    b       common_exceptionThrown      @ no, handle exception
9188
9189/* continuation for OP_SPUT_WIDE_VOLATILE */
9190
9191    /*
9192     * Continuation if the field has not yet been resolved.
9193     *  r1: BBBB field ref
9194     *  r9: &fp[AA]
9195     *
9196     * Returns StaticField pointer in r2.
9197     */
9198.LOP_SPUT_WIDE_VOLATILE_resolve:
9199    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9200    EXPORT_PC()                         @ resolve() could throw, so export now
9201    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9202    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9203    cmp     r0, #0                      @ success?
9204    mov     r2, r0                      @ copy to r2
9205    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9206    b       common_exceptionThrown      @ no, handle exception
9207
9208/* continuation for OP_EXECUTE_INLINE */
9209
9210    /*
9211     * Extract args, call function.
9212     *  r0 = #of args (0-4)
9213     *  r10 = call index
9214     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9215     *
9216     * Other ideas:
9217     * - Use a jump table from the main piece to jump directly into the
9218     *   AND/LDR pairs.  Costs a data load, saves a branch.
9219     * - Have five separate pieces that do the loading, so we can work the
9220     *   interleave a little better.  Increases code size.
9221     */
9222.LOP_EXECUTE_INLINE_continue:
9223    rsb     r0, r0, #4                  @ r0<- 4-r0
9224    FETCH(r9, 2)                        @ r9<- FEDC
9225    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9226    bl      common_abort                @ (skipped due to ARM prefetch)
92274:  and     ip, r9, #0xf000             @ isolate F
9228    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92293:  and     ip, r9, #0x0f00             @ isolate E
9230    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92312:  and     ip, r9, #0x00f0             @ isolate D
9232    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92331:  and     ip, r9, #0x000f             @ isolate C
9234    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92350:
9236    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9237    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9238    @ (not reached)
9239
9240.LOP_EXECUTE_INLINE_table:
9241    .word   gDvmInlineOpsTable
9242
9243/* continuation for OP_EXECUTE_INLINE_RANGE */
9244
9245    /*
9246     * Extract args, call function.
9247     *  r0 = #of args (0-4)
9248     *  r10 = call index
9249     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9250     */
9251.LOP_EXECUTE_INLINE_RANGE_continue:
9252    rsb     r0, r0, #4                  @ r0<- 4-r0
9253    FETCH(r9, 2)                        @ r9<- CCCC
9254    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9255    bl      common_abort                @ (skipped due to ARM prefetch)
92564:  add     ip, r9, #3                  @ base+3
9257    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92583:  add     ip, r9, #2                  @ base+2
9259    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92602:  add     ip, r9, #1                  @ base+1
9261    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92621:  add     ip, r9, #0                  @ (nop)
9263    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92640:
9265    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9266    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9267    @ (not reached)
9268
9269.LOP_EXECUTE_INLINE_RANGE_table:
9270    .word   gDvmInlineOpsTable
9271
9272/* continuation for OP_IPUT_OBJECT_VOLATILE */
9273
9274    /*
9275     * Currently:
9276     *  r0 holds resolved field
9277     *  r9 holds object
9278     */
9279.LOP_IPUT_OBJECT_VOLATILE_finish:
9280    @bl      common_squeak0
9281    mov     r1, rINST, lsr #8           @ r1<- A+
9282    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9283    and     r1, r1, #15                 @ r1<- A
9284    cmp     r9, #0                      @ check object for null
9285    GET_VREG(r0, r1)                    @ r0<- fp[A]
9286    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9287    beq     common_errNullObject        @ object was null
9288    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9289    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9290    SMP_DMB                            @ releasing store
9291    str     r0, [r9,r3]                 @ obj.field (32 bits)<- r0
9292    cmp     r0, #0                      @ stored a null reference?
9293    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9294    GOTO_OPCODE(ip)                     @ jump to next instruction
9295
9296/* continuation for OP_SGET_OBJECT_VOLATILE */
9297
9298    /*
9299     * Continuation if the field has not yet been resolved.
9300     *  r1: BBBB field ref
9301     */
9302.LOP_SGET_OBJECT_VOLATILE_resolve:
9303    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9304    EXPORT_PC()                         @ resolve() could throw, so export now
9305    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9306    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9307    cmp     r0, #0                      @ success?
9308    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9309    b       common_exceptionThrown      @ no, handle exception
9310
9311/* continuation for OP_SPUT_OBJECT_VOLATILE */
9312.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0, method in r9
9313    mov     r2, rINST, lsr #8           @ r2<- AA
9314    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9315    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9316    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9317    ldr     r9, [r9, #offMethod_clazz]  @ r9<- obj head
9318    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9319    add     r0, #offStaticField_value   @ r0<- pointer to store target
9320    SMP_DMB                            @ releasing store
9321    str     r1, [r0]                    @ field<- vAA
9322    cmp     r1, #0                      @ stored a null object?
9323    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9324    GOTO_OPCODE(ip)                     @ jump to next instruction
9325
9326    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9327    .global dvmAsmSisterEnd
9328dvmAsmSisterEnd:
9329
9330/* File: armv5te/footer.S */
9331
9332/*
9333 * ===========================================================================
9334 *  Common subroutines and data
9335 * ===========================================================================
9336 */
9337
9338
9339
9340    .text
9341    .align  2
9342
9343#if defined(WITH_JIT)
9344#if defined(WITH_SELF_VERIFICATION)
9345    .global dvmJitToInterpPunt
9346dvmJitToInterpPunt:
9347    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9348    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9349    mov    r3, #0
9350    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9351    b      jitSVShadowRunEnd            @ doesn't return
9352
9353    .global dvmJitToInterpSingleStep
9354dvmJitToInterpSingleStep:
9355    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9356    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9357    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9358    b      jitSVShadowRunEnd            @ doesn't return
9359
9360    .global dvmJitToInterpNoChainNoProfile
9361dvmJitToInterpNoChainNoProfile:
9362    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9363    mov    r0,rPC                       @ pass our target PC
9364    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9365    mov    r3, #0                       @ 0 means !inJitCodeCache
9366    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9367    b      jitSVShadowRunEnd            @ doesn't return
9368
9369    .global dvmJitToInterpTraceSelectNoChain
9370dvmJitToInterpTraceSelectNoChain:
9371    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9372    mov    r0,rPC                       @ pass our target PC
9373    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9374    mov    r3, #0                       @ 0 means !inJitCodeCache
9375    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9376    b      jitSVShadowRunEnd            @ doesn't return
9377
9378    .global dvmJitToInterpTraceSelect
9379dvmJitToInterpTraceSelect:
9380    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9381    ldr    r0,[lr, #-1]                 @ pass our target PC
9382    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9383    mov    r3, #0                       @ 0 means !inJitCodeCache
9384    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9385    b      jitSVShadowRunEnd            @ doesn't return
9386
9387    .global dvmJitToInterpBackwardBranch
9388dvmJitToInterpBackwardBranch:
9389    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9390    ldr    r0,[lr, #-1]                 @ pass our target PC
9391    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9392    mov    r3, #0                       @ 0 means !inJitCodeCache
9393    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9394    b      jitSVShadowRunEnd            @ doesn't return
9395
9396    .global dvmJitToInterpNormal
9397dvmJitToInterpNormal:
9398    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9399    ldr    r0,[lr, #-1]                 @ pass our target PC
9400    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9401    mov    r3, #0                       @ 0 means !inJitCodeCache
9402    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9403    b      jitSVShadowRunEnd            @ doesn't return
9404
9405    .global dvmJitToInterpNoChain
9406dvmJitToInterpNoChain:
9407    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9408    mov    r0,rPC                       @ pass our target PC
9409    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9410    mov    r3, #0                       @ 0 means !inJitCodeCache
9411    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9412    b      jitSVShadowRunEnd            @ doesn't return
9413#else
9414/*
9415 * Return from the translation cache to the interpreter when the compiler is
9416 * having issues translating/executing a Dalvik instruction. We have to skip
9417 * the code cache lookup otherwise it is possible to indefinitely bouce
9418 * between the interpreter and the code cache if the instruction that fails
9419 * to be compiled happens to be at a trace start.
9420 */
9421    .global dvmJitToInterpPunt
9422dvmJitToInterpPunt:
9423    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9424    mov    rPC, r0
9425#if defined(WITH_JIT_TUNING)
9426    mov    r0,lr
9427    bl     dvmBumpPunt;
9428#endif
9429    EXPORT_PC()
9430    mov    r0, #0
9431    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9432    adrl   rIBASE, dvmAsmInstructionStart
9433    FETCH_INST()
9434    GET_INST_OPCODE(ip)
9435    GOTO_OPCODE(ip)
9436
9437/*
9438 * Return to the interpreter to handle a single instruction.
9439 * On entry:
9440 *    r0 <= PC
9441 *    r1 <= PC of resume instruction
9442 *    lr <= resume point in translation
9443 */
9444    .global dvmJitToInterpSingleStep
9445dvmJitToInterpSingleStep:
9446    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9447    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9448    mov    r1,#kInterpEntryInstr
9449    @ enum is 4 byte in aapcs-EABI
9450    str    r1, [rGLUE, #offGlue_entryPoint]
9451    mov    rPC,r0
9452    EXPORT_PC()
9453
9454    adrl   rIBASE, dvmAsmInstructionStart
9455    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9456    str    r2,[rGLUE,#offGlue_jitState]
9457    mov    r1,#1                  @ set changeInterp to bail to debug interp
9458    b      common_gotoBail
9459
9460/*
9461 * Return from the translation cache and immediately request
9462 * a translation for the exit target.  Commonly used for callees.
9463 */
9464    .global dvmJitToInterpTraceSelectNoChain
9465dvmJitToInterpTraceSelectNoChain:
9466#if defined(WITH_JIT_TUNING)
9467    bl     dvmBumpNoChain
9468#endif
9469    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9470    mov    r0,rPC
9471    bl     dvmJitGetCodeAddr        @ Is there a translation?
9472    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9473    mov    r1, rPC                  @ arg1 of translation may need this
9474    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9475    cmp    r0,#0                    @ !0 means translation exists
9476    bxne   r0                       @ continue native execution if so
9477    b      2f                       @ branch over to use the interpreter
9478
9479/*
9480 * Return from the translation cache and immediately request
9481 * a translation for the exit target.  Commonly used following
9482 * invokes.
9483 */
9484    .global dvmJitToInterpTraceSelect
9485dvmJitToInterpTraceSelect:
9486    ldr    rPC,[lr, #-1]           @ get our target PC
9487    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9488    add    rINST,lr,#-5            @ save start of chain branch
9489    add    rINST, #-4              @  .. which is 9 bytes back
9490    mov    r0,rPC
9491    bl     dvmJitGetCodeAddr       @ Is there a translation?
9492    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9493    cmp    r0,#0
9494    beq    2f
9495    mov    r1,rINST
9496    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9497    mov    r1, rPC                  @ arg1 of translation may need this
9498    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9499    cmp    r0,#0                    @ successful chain?
9500    bxne   r0                       @ continue native execution
9501    b      toInterpreter            @ didn't chain - resume with interpreter
9502
9503/* No translation, so request one if profiling isn't disabled*/
95042:
9505    adrl   rIBASE, dvmAsmInstructionStart
9506    GET_JIT_PROF_TABLE(r0)
9507    FETCH_INST()
9508    cmp    r0, #0
9509    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9510    bne    common_selectTrace
9511    GET_INST_OPCODE(ip)
9512    GOTO_OPCODE(ip)
9513
9514/*
9515 * Return from the translation cache to the interpreter.
9516 * The return was done with a BLX from thumb mode, and
9517 * the following 32-bit word contains the target rPC value.
9518 * Note that lr (r14) will have its low-order bit set to denote
9519 * its thumb-mode origin.
9520 *
9521 * We'll need to stash our lr origin away, recover the new
9522 * target and then check to see if there is a translation available
9523 * for our new target.  If so, we do a translation chain and
9524 * go back to native execution.  Otherwise, it's back to the
9525 * interpreter (after treating this entry as a potential
9526 * trace start).
9527 */
9528    .global dvmJitToInterpNormal
9529dvmJitToInterpNormal:
9530    ldr    rPC,[lr, #-1]           @ get our target PC
9531    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9532    add    rINST,lr,#-5            @ save start of chain branch
9533    add    rINST,#-4               @ .. which is 9 bytes back
9534#if defined(WITH_JIT_TUNING)
9535    bl     dvmBumpNormal
9536#endif
9537    mov    r0,rPC
9538    bl     dvmJitGetCodeAddr        @ Is there a translation?
9539    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9540    cmp    r0,#0
9541    beq    toInterpreter            @ go if not, otherwise do chain
9542    mov    r1,rINST
9543    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9544    mov    r1, rPC                  @ arg1 of translation may need this
9545    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9546    cmp    r0,#0                    @ successful chain?
9547    bxne   r0                       @ continue native execution
9548    b      toInterpreter            @ didn't chain - resume with interpreter
9549
9550/*
9551 * Return from the translation cache to the interpreter to do method invocation.
9552 * Check if translation exists for the callee, but don't chain to it.
9553 */
9554    .global dvmJitToInterpNoChainNoProfile
9555dvmJitToInterpNoChainNoProfile:
9556#if defined(WITH_JIT_TUNING)
9557    bl     dvmBumpNoChain
9558#endif
9559    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9560    mov    r0,rPC
9561    bl     dvmJitGetCodeAddr        @ Is there a translation?
9562    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9563    mov    r1, rPC                  @ arg1 of translation may need this
9564    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9565    cmp    r0,#0
9566    bxne   r0                       @ continue native execution if so
9567    EXPORT_PC()
9568    adrl   rIBASE, dvmAsmInstructionStart
9569    FETCH_INST()
9570    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9571    GOTO_OPCODE(ip)                     @ jump to next instruction
9572
9573/*
9574 * Return from the translation cache to the interpreter to do method invocation.
9575 * Check if translation exists for the callee, but don't chain to it.
9576 */
9577    .global dvmJitToInterpNoChain
9578dvmJitToInterpNoChain:
9579#if defined(WITH_JIT_TUNING)
9580    bl     dvmBumpNoChain
9581#endif
9582    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9583    mov    r0,rPC
9584    bl     dvmJitGetCodeAddr        @ Is there a translation?
9585    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9586    mov    r1, rPC                  @ arg1 of translation may need this
9587    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9588    cmp    r0,#0
9589    bxne   r0                       @ continue native execution if so
9590#endif
9591
9592/*
9593 * No translation, restore interpreter regs and start interpreting.
9594 * rGLUE & rFP were preserved in the translated code, and rPC has
9595 * already been restored by the time we get here.  We'll need to set
9596 * up rIBASE & rINST, and load the address of the JitTable into r0.
9597 */
9598toInterpreter:
9599    EXPORT_PC()
9600    adrl   rIBASE, dvmAsmInstructionStart
9601    FETCH_INST()
9602    GET_JIT_PROF_TABLE(r0)
9603    @ NOTE: intended fallthrough
9604
9605/*
9606 * Common code to update potential trace start counter, and initiate
9607 * a trace-build if appropriate.  On entry, rPC should point to the
9608 * next instruction to execute, and rINST should be already loaded with
9609 * the next opcode word, and r0 holds a pointer to the jit profile
9610 * table (pJitProfTable).
9611 */
9612common_testUpdateProfile:
9613    cmp     r0,#0
9614    GET_INST_OPCODE(ip)
9615    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9616
9617common_updateProfile:
9618    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9619    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9620    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9621    GET_INST_OPCODE(ip)
9622    subs    r1,r1,#1           @ decrement counter
9623    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9624    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9625
9626/*
9627 * Here, we switch to the debug interpreter to request
9628 * trace selection.  First, though, check to see if there
9629 * is already a native translation in place (and, if so,
9630 * jump to it now).
9631 */
9632    GET_JIT_THRESHOLD(r1)
9633    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9634    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9635    EXPORT_PC()
9636    mov     r0,rPC
9637    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9638    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9639    mov     r1, rPC                     @ arg1 of translation may need this
9640    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9641    cmp     r0,#0
9642#if !defined(WITH_SELF_VERIFICATION)
9643    bxne    r0                          @ jump to the translation
9644    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9645    @ fall-through to common_selectTrace
9646#else
9647    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9648    beq     common_selectTrace
9649    /*
9650     * At this point, we have a target translation.  However, if
9651     * that translation is actually the interpret-only pseudo-translation
9652     * we want to treat it the same as no translation.
9653     */
9654    mov     r10, r0                     @ save target
9655    bl      dvmCompilerGetInterpretTemplate
9656    cmp     r0, r10                     @ special case?
9657    bne     jitSVShadowRunStart         @ set up self verification shadow space
9658    @ Need to clear the inJitCodeCache flag
9659    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
9660    mov    r3, #0                       @ 0 means not in the JIT code cache
9661    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9662    GET_INST_OPCODE(ip)
9663    GOTO_OPCODE(ip)
9664    /* no return */
9665#endif
9666
9667/*
9668 * On entry:
9669 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9670 */
9671common_selectTrace:
9672    str     r2,[rGLUE,#offGlue_jitState]
9673    mov     r2,#kInterpEntryInstr       @ normal entry reason
9674    str     r2,[rGLUE,#offGlue_entryPoint]
9675    mov     r1,#1                       @ set changeInterp
9676    b       common_gotoBail
9677
9678#if defined(WITH_SELF_VERIFICATION)
9679/*
9680 * Save PC and registers to shadow memory for self verification mode
9681 * before jumping to native translation.
9682 * On entry:
9683 *    rPC, rFP, rGLUE: the values that they should contain
9684 *    r10: the address of the target translation.
9685 */
9686jitSVShadowRunStart:
9687    mov     r0,rPC                      @ r0<- program counter
9688    mov     r1,rFP                      @ r1<- frame pointer
9689    mov     r2,rGLUE                    @ r2<- InterpState pointer
9690    mov     r3,r10                      @ r3<- target translation
9691    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9692    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9693    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9694    bx      r10                         @ jump to the translation
9695
9696/*
9697 * Restore PC, registers, and interpState to original values
9698 * before jumping back to the interpreter.
9699 */
9700jitSVShadowRunEnd:
9701    mov    r1,rFP                        @ pass ending fp
9702    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9703    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9704    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9705    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9706    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9707    cmp    r1,#0                         @ check for punt condition
9708    beq    1f
9709    mov    r2,#kJitSelfVerification      @ ask for self verification
9710    str    r2,[rGLUE,#offGlue_jitState]
9711    mov    r2,#kInterpEntryInstr         @ normal entry reason
9712    str    r2,[rGLUE,#offGlue_entryPoint]
9713    mov    r1,#1                         @ set changeInterp
9714    b      common_gotoBail
9715
97161:                                       @ exit to interpreter without check
9717    EXPORT_PC()
9718    adrl   rIBASE, dvmAsmInstructionStart
9719    FETCH_INST()
9720    GET_INST_OPCODE(ip)
9721    GOTO_OPCODE(ip)
9722#endif
9723
9724#endif
9725
9726/*
9727 * Common code when a backward branch is taken.
9728 *
9729 * TODO: we could avoid a branch by just setting r0 and falling through
9730 * into the common_periodicChecks code, and having a test on r0 at the
9731 * end determine if we should return to the caller or update & branch to
9732 * the next instr.
9733 *
9734 * On entry:
9735 *  r9 is PC adjustment *in bytes*
9736 */
9737common_backwardBranch:
9738    mov     r0, #kInterpEntryInstr
9739    bl      common_periodicChecks
9740#if defined(WITH_JIT)
9741    GET_JIT_PROF_TABLE(r0)
9742    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9743    cmp     r0,#0
9744    bne     common_updateProfile
9745    GET_INST_OPCODE(ip)
9746    GOTO_OPCODE(ip)
9747#else
9748    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9749    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9750    GOTO_OPCODE(ip)                     @ jump to next instruction
9751#endif
9752
9753
9754/*
9755 * Need to see if the thread needs to be suspended or debugger/profiler
9756 * activity has begun.  If so, we suspend the thread or side-exit to
9757 * the debug interpreter as appropriate.
9758 *
9759 * The common case is no activity on any of these, so we want to figure
9760 * that out quickly.  If something is up, we can then sort out what.
9761 *
9762 * We want to be fast if the VM was built without debugger or profiler
9763 * support, but we also need to recognize that the system is usually
9764 * shipped with both of these enabled.
9765 *
9766 * TODO: reduce this so we're just checking a single location.
9767 *
9768 * On entry:
9769 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9770 *  r9 is trampoline PC adjustment *in bytes*
9771 */
9772common_periodicChecks:
9773    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9774
9775    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9776    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9777
9778    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9779
9780    cmp     r1, #0                      @ debugger enabled?
9781    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9782    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9783    orrnes  ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9784    /*
9785     * Don't switch the interpreter in the libdvm_traceview build even if the
9786     * profiler is active.
9787     * The code here is opted for less intrusion instead of performance.
9788     * That is, *pActiveProfilers is still loaded into r2 even though it is not
9789     * used when WITH_INLINE_PROFILING is defined.
9790     */
9791#if !defined(WITH_INLINE_PROFILING)
9792    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9793#endif
9794
9795
9796    bxeq    lr                          @ all zero, return
9797
9798    /*
9799     * One or more interesting events have happened.  Figure out what.
9800     *
9801     * If debugging or profiling are compiled in, we need to disambiguate.
9802     *
9803     * r0 still holds the reentry type.
9804     */
9805    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9806    cmp     ip, #0                      @ want suspend?
9807    beq     1f                          @ no, must be debugger/profiler
9808
9809    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9810#if defined(WITH_JIT)
9811    /*
9812     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9813     * doubles as the Jit's on/off switch.
9814     */
9815    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9816    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9817    ldr     r3, [r3] @ r3 <- pJitProfTable
9818    EXPORT_PC()                         @ need for precise GC
9819    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9820#else
9821    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9822    EXPORT_PC()                         @ need for precise GC
9823#endif
9824    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9825    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9826
9827    /*
9828     * Reload the debugger/profiler enable flags.  We're checking to see
9829     * if either of these got set while we were suspended.
9830     *
9831     * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9832     * is enabled or not as the profiling will be done inline.
9833     */
9834    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9835    cmp     r1, #0                      @ debugger enabled?
9836    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9837
9838#if !defined(WITH_INLINE_PROFILING)
9839    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9840    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9841    orrs    r1, r1, r2
9842#else
9843    cmp     r1, #0                      @ only consult the debuggerActive flag
9844#endif
9845
9846    beq     2f
9847
98481:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9849    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9850    add     rPC, rPC, r9                @ update rPC
9851    mov     r1, #1                      @ "want switch" = true
9852    b       common_gotoBail             @ side exit
9853
98542:
9855    bx      lr                          @ nothing to do, return
9856
9857
9858/*
9859 * The equivalent of "goto bail", this calls through the "bail handler".
9860 *
9861 * State registers will be saved to the "glue" area before bailing.
9862 *
9863 * On entry:
9864 *  r1 is "bool changeInterp", indicating if we want to switch to the
9865 *     other interpreter or just bail all the way out
9866 */
9867common_gotoBail:
9868    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9869    mov     r0, rGLUE                   @ r0<- glue ptr
9870    b       dvmMterpStdBail             @ call(glue, changeInterp)
9871
9872    @add     r1, r1, #1                  @ using (boolean+1)
9873    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9874    @bl      _longjmp                    @ does not return
9875    @bl      common_abort
9876
9877
9878/*
9879 * Common code for method invocation with range.
9880 *
9881 * On entry:
9882 *  r0 is "Method* methodToCall", the method we're trying to call
9883 */
9884common_invokeMethodRange:
9885.LinvokeNewRange:
9886    @ prepare to copy args to "outs" area of current frame
9887    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9888    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9889    beq     .LinvokeArgsDone            @ if no args, skip the rest
9890    FETCH(r1, 2)                        @ r1<- CCCC
9891
9892    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9893    @ (very few methods have > 10 args; could unroll for common cases)
9894    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9895    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9896    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
98971:  ldr     r1, [r3], #4                @ val = *fp++
9898    subs    r2, r2, #1                  @ count--
9899    str     r1, [r10], #4               @ *outs++ = val
9900    bne     1b                          @ ...while count != 0
9901    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9902    b       .LinvokeArgsDone
9903
9904/*
9905 * Common code for method invocation without range.
9906 *
9907 * On entry:
9908 *  r0 is "Method* methodToCall", the method we're trying to call
9909 */
9910common_invokeMethodNoRange:
9911.LinvokeNewNoRange:
9912    @ prepare to copy args to "outs" area of current frame
9913    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9914    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9915    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9916    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9917    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9918    beq     .LinvokeArgsDone
9919
9920    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9921.LinvokeNonRange:
9922    rsb     r2, r2, #5                  @ r2<- 5-r2
9923    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9924    bl      common_abort                @ (skipped due to ARM prefetch)
99255:  and     ip, rINST, #0x0f00          @ isolate A
9926    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9927    mov     r0, r0                      @ nop
9928    str     r2, [r10, #-4]!             @ *--outs = vA
99294:  and     ip, r1, #0xf000             @ isolate G
9930    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9931    mov     r0, r0                      @ nop
9932    str     r2, [r10, #-4]!             @ *--outs = vG
99333:  and     ip, r1, #0x0f00             @ isolate F
9934    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9935    mov     r0, r0                      @ nop
9936    str     r2, [r10, #-4]!             @ *--outs = vF
99372:  and     ip, r1, #0x00f0             @ isolate E
9938    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9939    mov     r0, r0                      @ nop
9940    str     r2, [r10, #-4]!             @ *--outs = vE
99411:  and     ip, r1, #0x000f             @ isolate D
9942    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9943    mov     r0, r0                      @ nop
9944    str     r2, [r10, #-4]!             @ *--outs = vD
99450:  @ fall through to .LinvokeArgsDone
9946
9947.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9948    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9949    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9950    @ find space for the new stack frame, check for overflow
9951    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9952    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9953    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9954@    bl      common_dumpRegs
9955    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9956    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9957    cmp     r3, r9                      @ bottom < interpStackEnd?
9958    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9959    blo     .LstackOverflow             @ yes, this frame will overflow stack
9960
9961    @ set up newSaveArea
9962#ifdef EASY_GDB
9963    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9964    str     ip, [r10, #offStackSaveArea_prevSave]
9965#endif
9966    str     rFP, [r10, #offStackSaveArea_prevFrame]
9967    str     rPC, [r10, #offStackSaveArea_savedPc]
9968#if defined(WITH_JIT)
9969    mov     r9, #0
9970    str     r9, [r10, #offStackSaveArea_returnAddr]
9971#endif
9972#if defined(WITH_INLINE_PROFILING)
9973    stmfd   sp!, {r0-r3}                @ preserve r0-r3
9974    mov     r1, r6
9975    @ r0=methodToCall, r1=rGlue
9976    bl      dvmFastMethodTraceEnter
9977    ldmfd   sp!, {r0-r3}                @ restore r0-r3
9978#endif
9979    str     r0, [r10, #offStackSaveArea_method]
9980    tst     r3, #ACC_NATIVE
9981    bne     .LinvokeNative
9982
9983    /*
9984    stmfd   sp!, {r0-r3}
9985    bl      common_printNewline
9986    mov     r0, rFP
9987    mov     r1, #0
9988    bl      dvmDumpFp
9989    ldmfd   sp!, {r0-r3}
9990    stmfd   sp!, {r0-r3}
9991    mov     r0, r1
9992    mov     r1, r10
9993    bl      dvmDumpFp
9994    bl      common_printNewline
9995    ldmfd   sp!, {r0-r3}
9996    */
9997
9998    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9999    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10000    mov     rPC, r2                         @ publish new rPC
10001    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10002
10003    @ Update "glue" values for the new method
10004    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10005    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10006    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10007#if defined(WITH_JIT)
10008    GET_JIT_PROF_TABLE(r0)
10009    mov     rFP, r1                         @ fp = newFp
10010    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10011    mov     rINST, r9                       @ publish new rINST
10012    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10013    cmp     r0,#0
10014    bne     common_updateProfile
10015    GOTO_OPCODE(ip)                         @ jump to next instruction
10016#else
10017    mov     rFP, r1                         @ fp = newFp
10018    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10019    mov     rINST, r9                       @ publish new rINST
10020    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10021    GOTO_OPCODE(ip)                         @ jump to next instruction
10022#endif
10023
10024.LinvokeNative:
10025    @ Prep for the native call
10026    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10027    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10028    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10029    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10030    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10031    mov     r9, r3                      @ r9<- glue->self (preserve)
10032
10033    mov     r2, r0                      @ r2<- methodToCall
10034    mov     r0, r1                      @ r0<- newFp (points to args)
10035    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10036
10037#ifdef ASSIST_DEBUGGER
10038    /* insert fake function header to help gdb find the stack frame */
10039    b       .Lskip
10040    .type   dalvik_mterp, %function
10041dalvik_mterp:
10042    .fnstart
10043    MTERP_ENTRY1
10044    MTERP_ENTRY2
10045.Lskip:
10046#endif
10047
10048#if defined(WITH_INLINE_PROFILING)
10049    @ r2=JNIMethod, r6=rGLUE
10050    stmfd   sp!, {r2,r6}
10051#endif
10052
10053    @mov     lr, pc                      @ set return addr
10054    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10055    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10056
10057#if defined(WITH_INLINE_PROFILING)
10058    @ r0=JNIMethod, r1=rGLUE
10059    ldmfd   sp!, {r0-r1}
10060    bl      dvmFastNativeMethodTraceExit
10061#endif
10062
10063#if defined(WITH_JIT)
10064    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10065#endif
10066
10067    @ native return; r9=self, r10=newSaveArea
10068    @ equivalent to dvmPopJniLocals
10069    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10070    ldr     r1, [r9, #offThread_exception] @ check for exception
10071#if defined(WITH_JIT)
10072    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10073#endif
10074    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10075    cmp     r1, #0                      @ null?
10076    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10077#if defined(WITH_JIT)
10078    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10079#endif
10080    bne     common_exceptionThrown      @ no, handle exception
10081
10082    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10084    GOTO_OPCODE(ip)                     @ jump to next instruction
10085
10086.LstackOverflow:    @ r0=methodToCall
10087    mov     r1, r0                      @ r1<- methodToCall
10088    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10089    bl      dvmHandleStackOverflow
10090    b       common_exceptionThrown
10091#ifdef ASSIST_DEBUGGER
10092    .fnend
10093#endif
10094
10095
10096    /*
10097     * Common code for method invocation, calling through "glue code".
10098     *
10099     * TODO: now that we have range and non-range invoke handlers, this
10100     *       needs to be split into two.  Maybe just create entry points
10101     *       that set r9 and jump here?
10102     *
10103     * On entry:
10104     *  r0 is "Method* methodToCall", the method we're trying to call
10105     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10106     */
10107     .if    0
10108.LinvokeOld:
10109    sub     sp, sp, #8                  @ space for args + pad
10110    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10111    mov     r2, r0                      @ A2<- methodToCall
10112    mov     r0, rGLUE                   @ A0<- glue
10113    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10114    mov     r1, r9                      @ A1<- methodCallRange
10115    mov     r3, rINST, lsr #8           @ A3<- AA
10116    str     ip, [sp, #0]                @ A4<- ip
10117    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10118    add     sp, sp, #8                  @ remove arg area
10119    b       common_resumeAfterGlueCall  @ continue to next instruction
10120    .endif
10121
10122
10123
10124/*
10125 * Common code for handling a return instruction.
10126 *
10127 * This does not return.
10128 */
10129common_returnFromMethod:
10130.LreturnNew:
10131    mov     r0, #kInterpEntryReturn
10132    mov     r9, #0
10133    bl      common_periodicChecks
10134
10135#if defined(WITH_INLINE_PROFILING)
10136    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10137    mov     r0, r6
10138    @ r0=rGlue
10139    bl      dvmFastJavaMethodTraceExit
10140    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10141#endif
10142    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10143    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10144    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10145    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10146                                        @ r2<- method we're returning to
10147    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10148    cmp     r2, #0                      @ is this a break frame?
10149    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10150    mov     r1, #0                      @ "want switch" = false
10151    beq     common_gotoBail             @ break frame, bail out completely
10152
10153    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10154    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10155    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10156    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10157#if defined(WITH_JIT)
10158    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10159    mov     rPC, r9                     @ publish new rPC
10160    str     r1, [rGLUE, #offGlue_methodClassDex]
10161    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10162    cmp     r10, #0                      @ caller is compiled code
10163    blxne   r10
10164    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10165    GOTO_OPCODE(ip)                     @ jump to next instruction
10166#else
10167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10168    mov     rPC, r9                     @ publish new rPC
10169    str     r1, [rGLUE, #offGlue_methodClassDex]
10170    GOTO_OPCODE(ip)                     @ jump to next instruction
10171#endif
10172
10173    /*
10174     * Return handling, calls through "glue code".
10175     */
10176     .if    0
10177.LreturnOld:
10178    SAVE_PC_FP_TO_GLUE()                @ export state
10179    mov     r0, rGLUE                   @ arg to function
10180    bl      dvmMterp_returnFromMethod
10181    b       common_resumeAfterGlueCall
10182    .endif
10183
10184
10185/*
10186 * Somebody has thrown an exception.  Handle it.
10187 *
10188 * If the exception processing code returns to us (instead of falling
10189 * out of the interpreter), continue with whatever the next instruction
10190 * now happens to be.
10191 *
10192 * This does not return.
10193 */
10194     .global dvmMterpCommonExceptionThrown
10195dvmMterpCommonExceptionThrown:
10196common_exceptionThrown:
10197.LexceptionNew:
10198    mov     r0, #kInterpEntryThrow
10199    mov     r9, #0
10200    bl      common_periodicChecks
10201
10202    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10203    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10204    mov     r1, r10                     @ r1<- self
10205    mov     r0, r9                      @ r0<- exception
10206    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10207    mov     r3, #0                      @ r3<- NULL
10208    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10209
10210    /* set up args and a local for "&fp" */
10211    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10212    str     rFP, [sp, #-4]!             @ *--sp = fp
10213    mov     ip, sp                      @ ip<- &fp
10214    mov     r3, #0                      @ r3<- false
10215    str     ip, [sp, #-4]!              @ *--sp = &fp
10216    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10217    mov     r0, r10                     @ r0<- self
10218    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10219    mov     r2, r9                      @ r2<- exception
10220    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10221    mov     r1, r1, asr #1              @ r1<- offset in code units
10222
10223    /* call, r0 gets catchRelPc (a code-unit offset) */
10224    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10225
10226    /* fix earlier stack overflow if necessary; may trash rFP */
10227    ldrb    r1, [r10, #offThread_stackOverflowed]
10228    cmp     r1, #0                      @ did we overflow earlier?
10229    beq     1f                          @ no, skip ahead
10230    mov     rFP, r0                     @ save relPc result in rFP
10231    mov     r0, r10                     @ r0<- self
10232    mov     r1, r9                      @ r1<- exception
10233    bl      dvmCleanupStackOverflow     @ call(self)
10234    mov     r0, rFP                     @ restore result
102351:
10236
10237    /* update frame pointer and check result from dvmFindCatchBlock */
10238    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10239    cmp     r0, #0                      @ is catchRelPc < 0?
10240    add     sp, sp, #8                  @ restore stack
10241    bmi     .LnotCaughtLocally
10242
10243    /* adjust locals to match self->curFrame and updated PC */
10244    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10245    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10246    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10247    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10248    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10249    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10250    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10251    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10252
10253    /* release the tracked alloc on the exception */
10254    mov     r0, r9                      @ r0<- exception
10255    mov     r1, r10                     @ r1<- self
10256    bl      dvmReleaseTrackedAlloc      @ release the exception
10257
10258    /* restore the exception if the handler wants it */
10259    FETCH_INST()                        @ load rINST from rPC
10260    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10261    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10262    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10263    GOTO_OPCODE(ip)                     @ jump to next instruction
10264
10265.LnotCaughtLocally: @ r9=exception, r10=self
10266    /* fix stack overflow if necessary */
10267    ldrb    r1, [r10, #offThread_stackOverflowed]
10268    cmp     r1, #0                      @ did we overflow earlier?
10269    movne   r0, r10                     @ if yes: r0<- self
10270    movne   r1, r9                      @ if yes: r1<- exception
10271    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10272
10273    @ may want to show "not caught locally" debug messages here
10274#if DVM_SHOW_EXCEPTION >= 2
10275    /* call __android_log_print(prio, tag, format, ...) */
10276    /* "Exception %s from %s:%d not caught locally" */
10277    @ dvmLineNumFromPC(method, pc - method->insns)
10278    ldr     r0, [rGLUE, #offGlue_method]
10279    ldr     r1, [r0, #offMethod_insns]
10280    sub     r1, rPC, r1
10281    asr     r1, r1, #1
10282    bl      dvmLineNumFromPC
10283    str     r0, [sp, #-4]!
10284    @ dvmGetMethodSourceFile(method)
10285    ldr     r0, [rGLUE, #offGlue_method]
10286    bl      dvmGetMethodSourceFile
10287    str     r0, [sp, #-4]!
10288    @ exception->clazz->descriptor
10289    ldr     r3, [r9, #offObject_clazz]
10290    ldr     r3, [r3, #offClassObject_descriptor]
10291    @
10292    ldr     r2, strExceptionNotCaughtLocally
10293    ldr     r1, strLogTag
10294    mov     r0, #3                      @ LOG_DEBUG
10295    bl      __android_log_print
10296#endif
10297    str     r9, [r10, #offThread_exception] @ restore exception
10298    mov     r0, r9                      @ r0<- exception
10299    mov     r1, r10                     @ r1<- self
10300    bl      dvmReleaseTrackedAlloc      @ release the exception
10301    mov     r1, #0                      @ "want switch" = false
10302    b       common_gotoBail             @ bail out
10303
10304
10305    /*
10306     * Exception handling, calls through "glue code".
10307     */
10308    .if     0
10309.LexceptionOld:
10310    SAVE_PC_FP_TO_GLUE()                @ export state
10311    mov     r0, rGLUE                   @ arg to function
10312    bl      dvmMterp_exceptionThrown
10313    b       common_resumeAfterGlueCall
10314    .endif
10315
10316
10317/*
10318 * After returning from a "glued" function, pull out the updated
10319 * values and start executing at the next instruction.
10320 */
10321common_resumeAfterGlueCall:
10322    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10323    FETCH_INST()                        @ load rINST from rPC
10324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10325    GOTO_OPCODE(ip)                     @ jump to next instruction
10326
10327/*
10328 * Invalid array index.
10329 */
10330common_errArrayIndex:
10331    EXPORT_PC()
10332    ldr     r0, strArrayIndexException
10333    mov     r1, #0
10334    bl      dvmThrowException
10335    b       common_exceptionThrown
10336
10337/*
10338 * Invalid array value.
10339 */
10340common_errArrayStore:
10341    EXPORT_PC()
10342    ldr     r0, strArrayStoreException
10343    mov     r1, #0
10344    bl      dvmThrowException
10345    b       common_exceptionThrown
10346
10347/*
10348 * Integer divide or mod by zero.
10349 */
10350common_errDivideByZero:
10351    EXPORT_PC()
10352    ldr     r0, strArithmeticException
10353    ldr     r1, strDivideByZero
10354    bl      dvmThrowException
10355    b       common_exceptionThrown
10356
10357/*
10358 * Attempt to allocate an array with a negative size.
10359 */
10360common_errNegativeArraySize:
10361    EXPORT_PC()
10362    ldr     r0, strNegativeArraySizeException
10363    mov     r1, #0
10364    bl      dvmThrowException
10365    b       common_exceptionThrown
10366
10367/*
10368 * Invocation of a non-existent method.
10369 */
10370common_errNoSuchMethod:
10371    EXPORT_PC()
10372    ldr     r0, strNoSuchMethodError
10373    mov     r1, #0
10374    bl      dvmThrowException
10375    b       common_exceptionThrown
10376
10377/*
10378 * We encountered a null object when we weren't expecting one.  We
10379 * export the PC, throw a NullPointerException, and goto the exception
10380 * processing code.
10381 */
10382common_errNullObject:
10383    EXPORT_PC()
10384    ldr     r0, strNullPointerException
10385    mov     r1, #0
10386    bl      dvmThrowException
10387    b       common_exceptionThrown
10388
10389/*
10390 * For debugging, cause an immediate fault.  The source address will
10391 * be in lr (use a bl instruction to jump here).
10392 */
10393common_abort:
10394    ldr     pc, .LdeadFood
10395.LdeadFood:
10396    .word   0xdeadf00d
10397
10398/*
10399 * Spit out a "we were here", preserving all registers.  (The attempt
10400 * to save ip won't work, but we need to save an even number of
10401 * registers for EABI 64-bit stack alignment.)
10402 */
10403    .macro  SQUEAK num
10404common_squeak\num:
10405    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10406    ldr     r0, strSqueak
10407    mov     r1, #\num
10408    bl      printf
10409    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10410    bx      lr
10411    .endm
10412
10413    SQUEAK  0
10414    SQUEAK  1
10415    SQUEAK  2
10416    SQUEAK  3
10417    SQUEAK  4
10418    SQUEAK  5
10419
10420/*
10421 * Spit out the number in r0, preserving registers.
10422 */
10423common_printNum:
10424    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10425    mov     r1, r0
10426    ldr     r0, strSqueak
10427    bl      printf
10428    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10429    bx      lr
10430
10431/*
10432 * Print a newline, preserving registers.
10433 */
10434common_printNewline:
10435    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10436    ldr     r0, strNewline
10437    bl      printf
10438    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10439    bx      lr
10440
10441    /*
10442     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10443     */
10444common_printHex:
10445    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10446    mov     r1, r0
10447    ldr     r0, strPrintHex
10448    bl      printf
10449    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10450    bx      lr
10451
10452/*
10453 * Print the 64-bit quantity in r0-r1, preserving registers.
10454 */
10455common_printLong:
10456    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10457    mov     r3, r1
10458    mov     r2, r0
10459    ldr     r0, strPrintLong
10460    bl      printf
10461    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10462    bx      lr
10463
10464/*
10465 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10466 */
10467common_printMethod:
10468    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10469    bl      dvmMterpPrintMethod
10470    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10471    bx      lr
10472
10473/*
10474 * Call a C helper function that dumps regs and possibly some
10475 * additional info.  Requires the C function to be compiled in.
10476 */
10477    .if     0
10478common_dumpRegs:
10479    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10480    bl      dvmMterpDumpArmRegs
10481    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10482    bx      lr
10483    .endif
10484
10485#if 0
10486/*
10487 * Experiment on VFP mode.
10488 *
10489 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10490 *
10491 * Updates the bits specified by "mask", setting them to the values in "val".
10492 */
10493setFPSCR:
10494    and     r0, r0, r1                  @ make sure no stray bits are set
10495    fmrx    r2, fpscr                   @ get VFP reg
10496    mvn     r1, r1                      @ bit-invert mask
10497    and     r2, r2, r1                  @ clear masked bits
10498    orr     r2, r2, r0                  @ set specified bits
10499    fmxr    fpscr, r2                   @ set VFP reg
10500    mov     r0, r2                      @ return new value
10501    bx      lr
10502
10503    .align  2
10504    .global dvmConfigureFP
10505    .type   dvmConfigureFP, %function
10506dvmConfigureFP:
10507    stmfd   sp!, {ip, lr}
10508    /* 0x03000000 sets DN/FZ */
10509    /* 0x00009f00 clears the six exception enable flags */
10510    bl      common_squeak0
10511    mov     r0, #0x03000000             @ r0<- 0x03000000
10512    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10513    bl      setFPSCR
10514    ldmfd   sp!, {ip, pc}
10515#endif
10516
10517
10518/*
10519 * String references, must be close to the code that uses them.
10520 */
10521    .align  2
10522strArithmeticException:
10523    .word   .LstrArithmeticException
10524strArrayIndexException:
10525    .word   .LstrArrayIndexException
10526strArrayStoreException:
10527    .word   .LstrArrayStoreException
10528strDivideByZero:
10529    .word   .LstrDivideByZero
10530strNegativeArraySizeException:
10531    .word   .LstrNegativeArraySizeException
10532strNoSuchMethodError:
10533    .word   .LstrNoSuchMethodError
10534strNullPointerException:
10535    .word   .LstrNullPointerException
10536
10537strLogTag:
10538    .word   .LstrLogTag
10539strExceptionNotCaughtLocally:
10540    .word   .LstrExceptionNotCaughtLocally
10541
10542strNewline:
10543    .word   .LstrNewline
10544strSqueak:
10545    .word   .LstrSqueak
10546strPrintHex:
10547    .word   .LstrPrintHex
10548strPrintLong:
10549    .word   .LstrPrintLong
10550
10551/*
10552 * Zero-terminated ASCII string data.
10553 *
10554 * On ARM we have two choices: do like gcc does, and LDR from a .word
10555 * with the address, or use an ADR pseudo-op to get the address
10556 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10557 * PC-relative addressing mode and hence has a limited range, which
10558 * makes it not work well with mergeable string sections.
10559 */
10560    .section .rodata.str1.4,"aMS",%progbits,1
10561
10562.LstrBadEntryPoint:
10563    .asciz  "Bad entry point %d\n"
10564.LstrArithmeticException:
10565    .asciz  "Ljava/lang/ArithmeticException;"
10566.LstrArrayIndexException:
10567    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10568.LstrArrayStoreException:
10569    .asciz  "Ljava/lang/ArrayStoreException;"
10570.LstrClassCastException:
10571    .asciz  "Ljava/lang/ClassCastException;"
10572.LstrDivideByZero:
10573    .asciz  "divide by zero"
10574.LstrFilledNewArrayNotImpl:
10575    .asciz  "filled-new-array only implemented for objects and 'int'"
10576.LstrInternalError:
10577    .asciz  "Ljava/lang/InternalError;"
10578.LstrInstantiationError:
10579    .asciz  "Ljava/lang/InstantiationError;"
10580.LstrNegativeArraySizeException:
10581    .asciz  "Ljava/lang/NegativeArraySizeException;"
10582.LstrNoSuchMethodError:
10583    .asciz  "Ljava/lang/NoSuchMethodError;"
10584.LstrNullPointerException:
10585    .asciz  "Ljava/lang/NullPointerException;"
10586
10587.LstrLogTag:
10588    .asciz  "mterp"
10589.LstrExceptionNotCaughtLocally:
10590    .asciz  "Exception %s from %s:%d not caught locally\n"
10591
10592.LstrNewline:
10593    .asciz  "\n"
10594.LstrSqueak:
10595    .asciz  "<%d>"
10596.LstrPrintHex:
10597    .asciz  "<0x%x>"
10598.LstrPrintLong:
10599    .asciz  "<%lld>"
10600
10601