InterpAsm-armv7-a.S revision d88756df5b4dbc6fd450afd0019a5f64ebe4432d
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv7-a'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/*
25 * ARMv5 definitions and declarations.
26 */
27
28/*
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#if !defined(ANDROID_SMP)
217# error "Must define ANDROID_SMP"
218#endif
219
220/*
221 * Macro for data memory barrier.
222 */
223.macro  SMP_DMB
224#if ANDROID_SMP != 0
225    dmb
226#else
227    /* not SMP */
228#endif
229.endm
230
231/*
232 * Macro for data memory barrier (store/store variant).
233 */
234.macro  SMP_DMB_ST
235#if ANDROID_SMP != 0
236    dmb     st
237#else
238    /* not SMP */
239#endif
240.endm
241
242/* File: armv5te/entry.S */
243/*
244 * Copyright (C) 2008 The Android Open Source Project
245 *
246 * Licensed under the Apache License, Version 2.0 (the "License");
247 * you may not use this file except in compliance with the License.
248 * You may obtain a copy of the License at
249 *
250 *      http://www.apache.org/licenses/LICENSE-2.0
251 *
252 * Unless required by applicable law or agreed to in writing, software
253 * distributed under the License is distributed on an "AS IS" BASIS,
254 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
255 * See the License for the specific language governing permissions and
256 * limitations under the License.
257 */
258/*
259 * Interpreter entry point.
260 */
261
262/*
263 * We don't have formal stack frames, so gdb scans upward in the code
264 * to find the start of the function (a label with the %function type),
265 * and then looks at the next few instructions to figure out what
266 * got pushed onto the stack.  From this it figures out how to restore
267 * the registers, including PC, for the previous stack frame.  If gdb
268 * sees a non-function label, it stops scanning, so either we need to
269 * have nothing but assembler-local labels between the entry point and
270 * the break, or we need to fake it out.
271 *
272 * When this is defined, we add some stuff to make gdb less confused.
273 */
274#define ASSIST_DEBUGGER 1
275
276    .text
277    .align  2
278    .global dvmMterpStdRun
279    .type   dvmMterpStdRun, %function
280
281/*
282 * On entry:
283 *  r0  MterpGlue* glue
284 *
285 * This function returns a boolean "changeInterp" value.  The return comes
286 * via a call to dvmMterpStdBail().
287 */
288dvmMterpStdRun:
289#define MTERP_ENTRY1 \
290    .save {r4-r10,fp,lr}; \
291    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
292#define MTERP_ENTRY2 \
293    .pad    #4; \
294    sub     sp, sp, #4                  @ align 64
295
296    .fnstart
297    MTERP_ENTRY1
298    MTERP_ENTRY2
299
300    /* save stack pointer, add magic word for debuggerd */
301    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
302
303    /* set up "named" registers, figure out entry point */
304    mov     rGLUE, r0                   @ set rGLUE
305    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
306    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
307    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
308    cmp     r1, #kInterpEntryInstr      @ usual case?
309    bne     .Lnot_instr                 @ no, handle it
310
311#if defined(WITH_JIT)
312.LentryInstr:
313    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
314    /* Entry is always a possible trace start */
315    GET_JIT_PROF_TABLE(r0)
316    FETCH_INST()
317    mov     r1, #0                      @ prepare the value for the new state
318    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
319    cmp     r0,#0                       @ is profiling disabled?
320#if !defined(WITH_SELF_VERIFICATION)
321    bne     common_updateProfile        @ profiling is enabled
322#else
323    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
324    beq     1f                          @ profiling is disabled
325    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
326    cmp     r3, #kSVSTraceSelect        @ hot trace following?
327    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
328    beq     common_selectTrace          @ go build the trace
329    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
330    beq     1f                          @ intrepret the next instruction
331    b       common_updateProfile        @ collect profiles
332#endif
3331:
334    GET_INST_OPCODE(ip)
335    GOTO_OPCODE(ip)
336#else
337    /* start executing the instruction at rPC */
338    FETCH_INST()                        @ load rINST from rPC
339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
340    GOTO_OPCODE(ip)                     @ jump to next instruction
341#endif
342
343.Lnot_instr:
344    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
345    beq     common_returnFromMethod
346
347.Lnot_return:
348    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
349    beq     common_exceptionThrown
350
351#if defined(WITH_JIT)
352.Lnot_throw:
353    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
354    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
355    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
356    bne     .Lbad_arg
357    cmp     rPC,r2
358    bne     .LentryInstr                @ must have branched, don't resume
359#if defined(WITH_SELF_VERIFICATION)
360    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
361    b       jitSVShadowRunStart         @ re-enter the translation after the
362                                        @ single-stepped instruction
363    @noreturn
364#endif
365    mov     r1, #kInterpEntryInstr
366    str     r1, [rGLUE, #offGlue_entryPoint]
367    bx      r10                         @ re-enter the translation
368#endif
369
370.Lbad_arg:
371    ldr     r0, strBadEntryPoint
372    @ r1 holds value of entryPoint
373    bl      printf
374    bl      dvmAbort
375    .fnend
376
377
378    .global dvmMterpStdBail
379    .type   dvmMterpStdBail, %function
380
381/*
382 * Restore the stack pointer and PC from the save point established on entry.
383 * This is essentially the same as a longjmp, but should be cheaper.  The
384 * last instruction causes us to return to whoever called dvmMterpStdRun.
385 *
386 * We pushed some registers on the stack in dvmMterpStdRun, then saved
387 * SP and LR.  Here we restore SP, restore the registers, and then restore
388 * LR to PC.
389 *
390 * On entry:
391 *  r0  MterpGlue* glue
392 *  r1  bool changeInterp
393 */
394dvmMterpStdBail:
395    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
396    mov     r0, r1                          @ return the changeInterp value
397    add     sp, sp, #4                      @ un-align 64
398    ldmfd   sp!, {r4-r10,fp,pc}             @ restore 9 regs and return
399
400
401/*
402 * String references.
403 */
404strBadEntryPoint:
405    .word   .LstrBadEntryPoint
406
407
408    .global dvmAsmInstructionStart
409    .type   dvmAsmInstructionStart, %function
410dvmAsmInstructionStart = .L_OP_NOP
411    .text
412
413/* ------------------------------ */
414    .balign 64
415.L_OP_NOP: /* 0x00 */
416/* File: armv5te/OP_NOP.S */
417    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
418    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
419    GOTO_OPCODE(ip)                     @ execute it
420
421#ifdef ASSIST_DEBUGGER
422    /* insert fake function header to help gdb find the stack frame */
423    .type   dalvik_inst, %function
424dalvik_inst:
425    .fnstart
426    MTERP_ENTRY1
427    MTERP_ENTRY2
428    .fnend
429#endif
430
431/* ------------------------------ */
432    .balign 64
433.L_OP_MOVE: /* 0x01 */
434/* File: armv6t2/OP_MOVE.S */
435    /* for move, move-object, long-to-int */
436    /* op vA, vB */
437    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
438    ubfx    r0, rINST, #8, #4           @ r0<- A from 11:8
439    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
440    GET_VREG(r2, r1)                    @ r2<- fp[B]
441    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
442    SET_VREG(r2, r0)                    @ fp[A]<- r2
443    GOTO_OPCODE(ip)                     @ execute next instruction
444
445/* ------------------------------ */
446    .balign 64
447.L_OP_MOVE_FROM16: /* 0x02 */
448/* File: armv5te/OP_MOVE_FROM16.S */
449    /* for: move/from16, move-object/from16 */
450    /* op vAA, vBBBB */
451    FETCH(r1, 1)                        @ r1<- BBBB
452    mov     r0, rINST, lsr #8           @ r0<- AA
453    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
454    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
456    SET_VREG(r2, r0)                    @ fp[AA]<- r2
457    GOTO_OPCODE(ip)                     @ jump to next instruction
458
459/* ------------------------------ */
460    .balign 64
461.L_OP_MOVE_16: /* 0x03 */
462/* File: armv5te/OP_MOVE_16.S */
463    /* for: move/16, move-object/16 */
464    /* op vAAAA, vBBBB */
465    FETCH(r1, 2)                        @ r1<- BBBB
466    FETCH(r0, 1)                        @ r0<- AAAA
467    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
468    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
469    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
470    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
471    GOTO_OPCODE(ip)                     @ jump to next instruction
472
473/* ------------------------------ */
474    .balign 64
475.L_OP_MOVE_WIDE: /* 0x04 */
476/* File: armv6t2/OP_MOVE_WIDE.S */
477    /* move-wide vA, vB */
478    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
479    mov     r3, rINST, lsr #12          @ r3<- B
480    ubfx    r2, rINST, #8, #4           @ r2<- A
481    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
482    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
483    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
484    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
486    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
487    GOTO_OPCODE(ip)                     @ jump to next instruction
488
489/* ------------------------------ */
490    .balign 64
491.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
492/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
493    /* move-wide/from16 vAA, vBBBB */
494    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
495    FETCH(r3, 1)                        @ r3<- BBBB
496    mov     r2, rINST, lsr #8           @ r2<- AA
497    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
498    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
499    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
500    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
501    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
502    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
503    GOTO_OPCODE(ip)                     @ jump to next instruction
504
505/* ------------------------------ */
506    .balign 64
507.L_OP_MOVE_WIDE_16: /* 0x06 */
508/* File: armv5te/OP_MOVE_WIDE_16.S */
509    /* move-wide/16 vAAAA, vBBBB */
510    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
511    FETCH(r3, 2)                        @ r3<- BBBB
512    FETCH(r2, 1)                        @ r2<- AAAA
513    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
514    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
515    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
516    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
517    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
518    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
519    GOTO_OPCODE(ip)                     @ jump to next instruction
520
521/* ------------------------------ */
522    .balign 64
523.L_OP_MOVE_OBJECT: /* 0x07 */
524/* File: armv5te/OP_MOVE_OBJECT.S */
525/* File: armv5te/OP_MOVE.S */
526    /* for move, move-object, long-to-int */
527    /* op vA, vB */
528    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
529    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
530    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
531    GET_VREG(r2, r1)                    @ r2<- fp[B]
532    and     r0, r0, #15
533    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
534    SET_VREG(r2, r0)                    @ fp[A]<- r2
535    GOTO_OPCODE(ip)                     @ execute next instruction
536
537
538/* ------------------------------ */
539    .balign 64
540.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
541/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
542/* File: armv5te/OP_MOVE_FROM16.S */
543    /* for: move/from16, move-object/from16 */
544    /* op vAA, vBBBB */
545    FETCH(r1, 1)                        @ r1<- BBBB
546    mov     r0, rINST, lsr #8           @ r0<- AA
547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
548    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
550    SET_VREG(r2, r0)                    @ fp[AA]<- r2
551    GOTO_OPCODE(ip)                     @ jump to next instruction
552
553
554/* ------------------------------ */
555    .balign 64
556.L_OP_MOVE_OBJECT_16: /* 0x09 */
557/* File: armv5te/OP_MOVE_OBJECT_16.S */
558/* File: armv5te/OP_MOVE_16.S */
559    /* for: move/16, move-object/16 */
560    /* op vAAAA, vBBBB */
561    FETCH(r1, 2)                        @ r1<- BBBB
562    FETCH(r0, 1)                        @ r0<- AAAA
563    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
564    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
565    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
566    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
567    GOTO_OPCODE(ip)                     @ jump to next instruction
568
569
570/* ------------------------------ */
571    .balign 64
572.L_OP_MOVE_RESULT: /* 0x0a */
573/* File: armv5te/OP_MOVE_RESULT.S */
574    /* for: move-result, move-result-object */
575    /* op vAA */
576    mov     r2, rINST, lsr #8           @ r2<- AA
577    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
578    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
579    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
580    SET_VREG(r0, r2)                    @ fp[AA]<- r0
581    GOTO_OPCODE(ip)                     @ jump to next instruction
582
583/* ------------------------------ */
584    .balign 64
585.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
586/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
587    /* move-result-wide vAA */
588    mov     r2, rINST, lsr #8           @ r2<- AA
589    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
590    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
591    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
592    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
594    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
595    GOTO_OPCODE(ip)                     @ jump to next instruction
596
597/* ------------------------------ */
598    .balign 64
599.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
600/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
601/* File: armv5te/OP_MOVE_RESULT.S */
602    /* for: move-result, move-result-object */
603    /* op vAA */
604    mov     r2, rINST, lsr #8           @ r2<- AA
605    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
606    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
607    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
608    SET_VREG(r0, r2)                    @ fp[AA]<- r0
609    GOTO_OPCODE(ip)                     @ jump to next instruction
610
611
612/* ------------------------------ */
613    .balign 64
614.L_OP_MOVE_EXCEPTION: /* 0x0d */
615/* File: armv5te/OP_MOVE_EXCEPTION.S */
616    /* move-exception vAA */
617    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
618    mov     r2, rINST, lsr #8           @ r2<- AA
619    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
620    mov     r1, #0                      @ r1<- 0
621    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
622    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
623    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
624    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
625    GOTO_OPCODE(ip)                     @ jump to next instruction
626
627/* ------------------------------ */
628    .balign 64
629.L_OP_RETURN_VOID: /* 0x0e */
630/* File: armv5te/OP_RETURN_VOID.S */
631    b       common_returnFromMethod
632
633/* ------------------------------ */
634    .balign 64
635.L_OP_RETURN: /* 0x0f */
636/* File: armv5te/OP_RETURN.S */
637    /*
638     * Return a 32-bit value.  Copies the return value into the "glue"
639     * structure, then jumps to the return handler.
640     *
641     * for: return, return-object
642     */
643    /* op vAA */
644    mov     r2, rINST, lsr #8           @ r2<- AA
645    GET_VREG(r0, r2)                    @ r0<- vAA
646    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
647    b       common_returnFromMethod
648
649/* ------------------------------ */
650    .balign 64
651.L_OP_RETURN_WIDE: /* 0x10 */
652/* File: armv5te/OP_RETURN_WIDE.S */
653    /*
654     * Return a 64-bit value.  Copies the return value into the "glue"
655     * structure, then jumps to the return handler.
656     */
657    /* return-wide vAA */
658    mov     r2, rINST, lsr #8           @ r2<- AA
659    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
660    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
661    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
662    stmia   r3, {r0-r1}                 @ retval<- r0/r1
663    b       common_returnFromMethod
664
665/* ------------------------------ */
666    .balign 64
667.L_OP_RETURN_OBJECT: /* 0x11 */
668/* File: armv5te/OP_RETURN_OBJECT.S */
669/* File: armv5te/OP_RETURN.S */
670    /*
671     * Return a 32-bit value.  Copies the return value into the "glue"
672     * structure, then jumps to the return handler.
673     *
674     * for: return, return-object
675     */
676    /* op vAA */
677    mov     r2, rINST, lsr #8           @ r2<- AA
678    GET_VREG(r0, r2)                    @ r0<- vAA
679    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
680    b       common_returnFromMethod
681
682
683/* ------------------------------ */
684    .balign 64
685.L_OP_CONST_4: /* 0x12 */
686/* File: armv6t2/OP_CONST_4.S */
687    /* const/4 vA, #+B */
688    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
689    ubfx    r0, rINST, #8, #4           @ r0<- A
690    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
691    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
692    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
693    SET_VREG(r1, r0)                    @ fp[A]<- r1
694    GOTO_OPCODE(ip)                     @ execute next instruction
695
696/* ------------------------------ */
697    .balign 64
698.L_OP_CONST_16: /* 0x13 */
699/* File: armv5te/OP_CONST_16.S */
700    /* const/16 vAA, #+BBBB */
701    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
702    mov     r3, rINST, lsr #8           @ r3<- AA
703    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
704    SET_VREG(r0, r3)                    @ vAA<- r0
705    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
706    GOTO_OPCODE(ip)                     @ jump to next instruction
707
708/* ------------------------------ */
709    .balign 64
710.L_OP_CONST: /* 0x14 */
711/* File: armv5te/OP_CONST.S */
712    /* const vAA, #+BBBBbbbb */
713    mov     r3, rINST, lsr #8           @ r3<- AA
714    FETCH(r0, 1)                        @ r0<- bbbb (low)
715    FETCH(r1, 2)                        @ r1<- BBBB (high)
716    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
717    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
719    SET_VREG(r0, r3)                    @ vAA<- r0
720    GOTO_OPCODE(ip)                     @ jump to next instruction
721
722/* ------------------------------ */
723    .balign 64
724.L_OP_CONST_HIGH16: /* 0x15 */
725/* File: armv5te/OP_CONST_HIGH16.S */
726    /* const/high16 vAA, #+BBBB0000 */
727    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
728    mov     r3, rINST, lsr #8           @ r3<- AA
729    mov     r0, r0, lsl #16             @ r0<- BBBB0000
730    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
731    SET_VREG(r0, r3)                    @ vAA<- r0
732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
733    GOTO_OPCODE(ip)                     @ jump to next instruction
734
735/* ------------------------------ */
736    .balign 64
737.L_OP_CONST_WIDE_16: /* 0x16 */
738/* File: armv5te/OP_CONST_WIDE_16.S */
739    /* const-wide/16 vAA, #+BBBB */
740    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
741    mov     r3, rINST, lsr #8           @ r3<- AA
742    mov     r1, r0, asr #31             @ r1<- ssssssss
743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
747    GOTO_OPCODE(ip)                     @ jump to next instruction
748
749/* ------------------------------ */
750    .balign 64
751.L_OP_CONST_WIDE_32: /* 0x17 */
752/* File: armv5te/OP_CONST_WIDE_32.S */
753    /* const-wide/32 vAA, #+BBBBbbbb */
754    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
755    mov     r3, rINST, lsr #8           @ r3<- AA
756    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
757    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
758    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
759    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
760    mov     r1, r0, asr #31             @ r1<- ssssssss
761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
762    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
763    GOTO_OPCODE(ip)                     @ jump to next instruction
764
765/* ------------------------------ */
766    .balign 64
767.L_OP_CONST_WIDE: /* 0x18 */
768/* File: armv5te/OP_CONST_WIDE.S */
769    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
770    FETCH(r0, 1)                        @ r0<- bbbb (low)
771    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
772    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
773    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
774    FETCH(r3, 4)                        @ r3<- HHHH (high)
775    mov     r9, rINST, lsr #8           @ r9<- AA
776    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
777    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
778    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
779    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
780    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
781    GOTO_OPCODE(ip)                     @ jump to next instruction
782
783/* ------------------------------ */
784    .balign 64
785.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
786/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
787    /* const-wide/high16 vAA, #+BBBB000000000000 */
788    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
789    mov     r3, rINST, lsr #8           @ r3<- AA
790    mov     r0, #0                      @ r0<- 00000000
791    mov     r1, r1, lsl #16             @ r1<- BBBB0000
792    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
793    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
795    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
796    GOTO_OPCODE(ip)                     @ jump to next instruction
797
798/* ------------------------------ */
799    .balign 64
800.L_OP_CONST_STRING: /* 0x1a */
801/* File: armv5te/OP_CONST_STRING.S */
802    /* const/string vAA, String@BBBB */
803    FETCH(r1, 1)                        @ r1<- BBBB
804    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
805    mov     r9, rINST, lsr #8           @ r9<- AA
806    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
807    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
808    cmp     r0, #0                      @ not yet resolved?
809    beq     .LOP_CONST_STRING_resolve
810    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
811    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
812    SET_VREG(r0, r9)                    @ vAA<- r0
813    GOTO_OPCODE(ip)                     @ jump to next instruction
814
815/* ------------------------------ */
816    .balign 64
817.L_OP_CONST_STRING_JUMBO: /* 0x1b */
818/* File: armv5te/OP_CONST_STRING_JUMBO.S */
819    /* const/string vAA, String@BBBBBBBB */
820    FETCH(r0, 1)                        @ r0<- bbbb (low)
821    FETCH(r1, 2)                        @ r1<- BBBB (high)
822    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
823    mov     r9, rINST, lsr #8           @ r9<- AA
824    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
825    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
826    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
827    cmp     r0, #0
828    beq     .LOP_CONST_STRING_JUMBO_resolve
829    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
831    SET_VREG(r0, r9)                    @ vAA<- r0
832    GOTO_OPCODE(ip)                     @ jump to next instruction
833
834/* ------------------------------ */
835    .balign 64
836.L_OP_CONST_CLASS: /* 0x1c */
837/* File: armv5te/OP_CONST_CLASS.S */
838    /* const/class vAA, Class@BBBB */
839    FETCH(r1, 1)                        @ r1<- BBBB
840    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
841    mov     r9, rINST, lsr #8           @ r9<- AA
842    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
843    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
844    cmp     r0, #0                      @ not yet resolved?
845    beq     .LOP_CONST_CLASS_resolve
846    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
848    SET_VREG(r0, r9)                    @ vAA<- r0
849    GOTO_OPCODE(ip)                     @ jump to next instruction
850
851/* ------------------------------ */
852    .balign 64
853.L_OP_MONITOR_ENTER: /* 0x1d */
854/* File: armv5te/OP_MONITOR_ENTER.S */
855    /*
856     * Synchronize on an object.
857     */
858    /* monitor-enter vAA */
859    mov     r2, rINST, lsr #8           @ r2<- AA
860    GET_VREG(r1, r2)                    @ r1<- vAA (object)
861    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
862    cmp     r1, #0                      @ null object?
863    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
864    beq     common_errNullObject        @ null object, throw an exception
865    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
866    bl      dvmLockObject               @ call(self, obj)
867#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
868    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
869    ldr     r1, [r0, #offThread_exception] @ check for exception
870    cmp     r1, #0
871    bne     common_exceptionThrown      @ exception raised, bail out
872#endif
873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
874    GOTO_OPCODE(ip)                     @ jump to next instruction
875
876/* ------------------------------ */
877    .balign 64
878.L_OP_MONITOR_EXIT: /* 0x1e */
879/* File: armv5te/OP_MONITOR_EXIT.S */
880    /*
881     * Unlock an object.
882     *
883     * Exceptions that occur when unlocking a monitor need to appear as
884     * if they happened at the following instruction.  See the Dalvik
885     * instruction spec.
886     */
887    /* monitor-exit vAA */
888    mov     r2, rINST, lsr #8           @ r2<- AA
889    EXPORT_PC()                         @ before fetch: export the PC
890    GET_VREG(r1, r2)                    @ r1<- vAA (object)
891    cmp     r1, #0                      @ null object?
892    beq     1f                          @ yes
893    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
894    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
895    cmp     r0, #0                      @ failed?
896    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
897    beq     common_exceptionThrown      @ yes, exception is pending
898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
899    GOTO_OPCODE(ip)                     @ jump to next instruction
9001:
901    FETCH_ADVANCE_INST(1)               @ advance before throw
902    b      common_errNullObject
903
904/* ------------------------------ */
905    .balign 64
906.L_OP_CHECK_CAST: /* 0x1f */
907/* File: armv5te/OP_CHECK_CAST.S */
908    /*
909     * Check to see if a cast from one class to another is allowed.
910     */
911    /* check-cast vAA, class@BBBB */
912    mov     r3, rINST, lsr #8           @ r3<- AA
913    FETCH(r2, 1)                        @ r2<- BBBB
914    GET_VREG(r9, r3)                    @ r9<- object
915    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
916    cmp     r9, #0                      @ is object null?
917    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
918    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
919    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
920    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
921    cmp     r1, #0                      @ have we resolved this before?
922    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
923.LOP_CHECK_CAST_resolved:
924    cmp     r0, r1                      @ same class (trivial success)?
925    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
926.LOP_CHECK_CAST_okay:
927    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
929    GOTO_OPCODE(ip)                     @ jump to next instruction
930
931/* ------------------------------ */
932    .balign 64
933.L_OP_INSTANCE_OF: /* 0x20 */
934/* File: armv5te/OP_INSTANCE_OF.S */
935    /*
936     * Check to see if an object reference is an instance of a class.
937     *
938     * Most common situation is a non-null object, being compared against
939     * an already-resolved class.
940     */
941    /* instance-of vA, vB, class@CCCC */
942    mov     r3, rINST, lsr #12          @ r3<- B
943    mov     r9, rINST, lsr #8           @ r9<- A+
944    GET_VREG(r0, r3)                    @ r0<- vB (object)
945    and     r9, r9, #15                 @ r9<- A
946    cmp     r0, #0                      @ is object null?
947    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
948    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
949    FETCH(r3, 1)                        @ r3<- CCCC
950    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
951    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
952    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
953    cmp     r1, #0                      @ have we resolved this before?
954    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
955.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
956    cmp     r0, r1                      @ same class (trivial success)?
957    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
958    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
959
960/* ------------------------------ */
961    .balign 64
962.L_OP_ARRAY_LENGTH: /* 0x21 */
963/* File: armv6t2/OP_ARRAY_LENGTH.S */
964    /*
965     * Return the length of an array.
966     */
967    mov     r1, rINST, lsr #12          @ r1<- B
968    ubfx    r2, rINST, #8, #4           @ r2<- A
969    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
970    cmp     r0, #0                      @ is object null?
971    beq     common_errNullObject        @ yup, fail
972    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
973    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
974    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
975    SET_VREG(r3, r2)                    @ vB<- length
976    GOTO_OPCODE(ip)                     @ jump to next instruction
977
978/* ------------------------------ */
979    .balign 64
980.L_OP_NEW_INSTANCE: /* 0x22 */
981/* File: armv5te/OP_NEW_INSTANCE.S */
982    /*
983     * Create a new instance of a class.
984     */
985    /* new-instance vAA, class@BBBB */
986    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
987    FETCH(r1, 1)                        @ r1<- BBBB
988    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
989    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
990    EXPORT_PC()                         @ req'd for init, resolve, alloc
991    cmp     r0, #0                      @ already resolved?
992    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
993.LOP_NEW_INSTANCE_resolved:   @ r0=class
994    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
995    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
996    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
997.LOP_NEW_INSTANCE_initialized: @ r0=class
998    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
999    bl      dvmAllocObject              @ r0<- new object
1000    b       .LOP_NEW_INSTANCE_finish          @ continue
1001
1002/* ------------------------------ */
1003    .balign 64
1004.L_OP_NEW_ARRAY: /* 0x23 */
1005/* File: armv5te/OP_NEW_ARRAY.S */
1006    /*
1007     * Allocate an array of objects, specified with the array class
1008     * and a count.
1009     *
1010     * The verifier guarantees that this is an array class, so we don't
1011     * check for it here.
1012     */
1013    /* new-array vA, vB, class@CCCC */
1014    mov     r0, rINST, lsr #12          @ r0<- B
1015    FETCH(r2, 1)                        @ r2<- CCCC
1016    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1017    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1018    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1019    cmp     r1, #0                      @ check length
1020    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1021    bmi     common_errNegativeArraySize @ negative length, bail
1022    cmp     r0, #0                      @ already resolved?
1023    EXPORT_PC()                         @ req'd for resolve, alloc
1024    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1025    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1026
1027/* ------------------------------ */
1028    .balign 64
1029.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1030/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1031    /*
1032     * Create a new array with elements filled from registers.
1033     *
1034     * for: filled-new-array, filled-new-array/range
1035     */
1036    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1037    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1038    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1039    FETCH(r1, 1)                        @ r1<- BBBB
1040    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1041    EXPORT_PC()                         @ need for resolve and alloc
1042    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1043    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1044    cmp     r0, #0                      @ already resolved?
1045    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10468:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1047    mov     r2, #0                      @ r2<- false
1048    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1049    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1050    cmp     r0, #0                      @ got null?
1051    beq     common_exceptionThrown      @ yes, handle exception
1052    b       .LOP_FILLED_NEW_ARRAY_continue
1053
1054/* ------------------------------ */
1055    .balign 64
1056.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1057/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1058/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1059    /*
1060     * Create a new array with elements filled from registers.
1061     *
1062     * for: filled-new-array, filled-new-array/range
1063     */
1064    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1065    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1066    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1067    FETCH(r1, 1)                        @ r1<- BBBB
1068    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1069    EXPORT_PC()                         @ need for resolve and alloc
1070    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1071    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1072    cmp     r0, #0                      @ already resolved?
1073    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10748:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1075    mov     r2, #0                      @ r2<- false
1076    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1077    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1078    cmp     r0, #0                      @ got null?
1079    beq     common_exceptionThrown      @ yes, handle exception
1080    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1081
1082
1083/* ------------------------------ */
1084    .balign 64
1085.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1086/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1087    /* fill-array-data vAA, +BBBBBBBB */
1088    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1089    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1090    mov     r3, rINST, lsr #8           @ r3<- AA
1091    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1092    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1093    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1094    EXPORT_PC();
1095    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1096    cmp     r0, #0                      @ 0 means an exception is thrown
1097    beq     common_exceptionThrown      @ has exception
1098    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1099    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1100    GOTO_OPCODE(ip)                     @ jump to next instruction
1101
1102/* ------------------------------ */
1103    .balign 64
1104.L_OP_THROW: /* 0x27 */
1105/* File: armv5te/OP_THROW.S */
1106    /*
1107     * Throw an exception object in the current thread.
1108     */
1109    /* throw vAA */
1110    mov     r2, rINST, lsr #8           @ r2<- AA
1111    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1112    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1113    EXPORT_PC()                         @ exception handler can throw
1114    cmp     r1, #0                      @ null object?
1115    beq     common_errNullObject        @ yes, throw an NPE instead
1116    @ bypass dvmSetException, just store it
1117    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1118    b       common_exceptionThrown
1119
1120/* ------------------------------ */
1121    .balign 64
1122.L_OP_GOTO: /* 0x28 */
1123/* File: armv5te/OP_GOTO.S */
1124    /*
1125     * Unconditional branch, 8-bit offset.
1126     *
1127     * The branch distance is a signed code-unit offset, which we need to
1128     * double to get a byte offset.
1129     */
1130    /* goto +AA */
1131    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1132    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1133    mov     r9, r9, lsl #1              @ r9<- byte offset
1134    bmi     common_backwardBranch       @ backward branch, do periodic checks
1135#if defined(WITH_JIT)
1136    GET_JIT_PROF_TABLE(r0)
1137    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1138    cmp     r0,#0
1139    bne     common_updateProfile
1140    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1141    GOTO_OPCODE(ip)                     @ jump to next instruction
1142#else
1143    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1145    GOTO_OPCODE(ip)                     @ jump to next instruction
1146#endif
1147
1148/* ------------------------------ */
1149    .balign 64
1150.L_OP_GOTO_16: /* 0x29 */
1151/* File: armv5te/OP_GOTO_16.S */
1152    /*
1153     * Unconditional branch, 16-bit offset.
1154     *
1155     * The branch distance is a signed code-unit offset, which we need to
1156     * double to get a byte offset.
1157     */
1158    /* goto/16 +AAAA */
1159    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1160    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1161    bmi     common_backwardBranch       @ backward branch, do periodic checks
1162#if defined(WITH_JIT)
1163    GET_JIT_PROF_TABLE(r0)
1164    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1165    cmp     r0,#0
1166    bne     common_updateProfile
1167    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1168    GOTO_OPCODE(ip)                     @ jump to next instruction
1169#else
1170    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1172    GOTO_OPCODE(ip)                     @ jump to next instruction
1173#endif
1174
1175/* ------------------------------ */
1176    .balign 64
1177.L_OP_GOTO_32: /* 0x2a */
1178/* File: armv5te/OP_GOTO_32.S */
1179    /*
1180     * Unconditional branch, 32-bit offset.
1181     *
1182     * The branch distance is a signed code-unit offset, which we need to
1183     * double to get a byte offset.
1184     *
1185     * Unlike most opcodes, this one is allowed to branch to itself, so
1186     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1187     * instruction doesn't affect the V flag, so we need to clear it
1188     * explicitly.
1189     */
1190    /* goto/32 +AAAAAAAA */
1191    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1192    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1193    cmp     ip, ip                      @ (clear V flag during stall)
1194    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1195    mov     r9, r0, asl #1              @ r9<- byte offset
1196    ble     common_backwardBranch       @ backward branch, do periodic checks
1197#if defined(WITH_JIT)
1198    GET_JIT_PROF_TABLE(r0)
1199    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1200    cmp     r0,#0
1201    bne     common_updateProfile
1202    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1203    GOTO_OPCODE(ip)                     @ jump to next instruction
1204#else
1205    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1207    GOTO_OPCODE(ip)                     @ jump to next instruction
1208#endif
1209
1210/* ------------------------------ */
1211    .balign 64
1212.L_OP_PACKED_SWITCH: /* 0x2b */
1213/* File: armv5te/OP_PACKED_SWITCH.S */
1214    /*
1215     * Handle a packed-switch or sparse-switch instruction.  In both cases
1216     * we decode it and hand it off to a helper function.
1217     *
1218     * We don't really expect backward branches in a switch statement, but
1219     * they're perfectly legal, so we check for them here.
1220     *
1221     * for: packed-switch, sparse-switch
1222     */
1223    /* op vAA, +BBBB */
1224    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1225    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1226    mov     r3, rINST, lsr #8           @ r3<- AA
1227    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1228    GET_VREG(r1, r3)                    @ r1<- vAA
1229    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1230    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1231    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1232    bmi     common_backwardBranch       @ backward branch, do periodic checks
1233    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1234#if defined(WITH_JIT)
1235    GET_JIT_PROF_TABLE(r0)
1236    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1237    cmp     r0,#0
1238    bne     common_updateProfile
1239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1240    GOTO_OPCODE(ip)                     @ jump to next instruction
1241#else
1242    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1243    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1244    GOTO_OPCODE(ip)                     @ jump to next instruction
1245#endif
1246
1247/* ------------------------------ */
1248    .balign 64
1249.L_OP_SPARSE_SWITCH: /* 0x2c */
1250/* File: armv5te/OP_SPARSE_SWITCH.S */
1251/* File: armv5te/OP_PACKED_SWITCH.S */
1252    /*
1253     * Handle a packed-switch or sparse-switch instruction.  In both cases
1254     * we decode it and hand it off to a helper function.
1255     *
1256     * We don't really expect backward branches in a switch statement, but
1257     * they're perfectly legal, so we check for them here.
1258     *
1259     * for: packed-switch, sparse-switch
1260     */
1261    /* op vAA, +BBBB */
1262    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1263    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1264    mov     r3, rINST, lsr #8           @ r3<- AA
1265    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1266    GET_VREG(r1, r3)                    @ r1<- vAA
1267    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1268    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1269    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1270    bmi     common_backwardBranch       @ backward branch, do periodic checks
1271    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1272#if defined(WITH_JIT)
1273    GET_JIT_PROF_TABLE(r0)
1274    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1275    cmp     r0,#0
1276    bne     common_updateProfile
1277    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1278    GOTO_OPCODE(ip)                     @ jump to next instruction
1279#else
1280    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1281    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1282    GOTO_OPCODE(ip)                     @ jump to next instruction
1283#endif
1284
1285
1286/* ------------------------------ */
1287    .balign 64
1288.L_OP_CMPL_FLOAT: /* 0x2d */
1289/* File: arm-vfp/OP_CMPL_FLOAT.S */
1290    /*
1291     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1292     * destination register based on the results of the comparison.
1293     *
1294     * int compare(x, y) {
1295     *     if (x == y) {
1296     *         return 0;
1297     *     } else if (x > y) {
1298     *         return 1;
1299     *     } else if (x < y) {
1300     *         return -1;
1301     *     } else {
1302     *         return -1;
1303     *     }
1304     * }
1305     */
1306    /* op vAA, vBB, vCC */
1307    FETCH(r0, 1)                        @ r0<- CCBB
1308    mov     r9, rINST, lsr #8           @ r9<- AA
1309    and     r2, r0, #255                @ r2<- BB
1310    mov     r3, r0, lsr #8              @ r3<- CC
1311    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1312    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1313    flds    s0, [r2]                    @ s0<- vBB
1314    flds    s1, [r3]                    @ s1<- vCC
1315    fcmpes  s0, s1                      @ compare (vBB, vCC)
1316    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1317    mvn     r0, #0                      @ r0<- -1 (default)
1318    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1319    fmstat                              @ export status flags
1320    movgt   r0, #1                      @ (greater than) r1<- 1
1321    moveq   r0, #0                      @ (equal) r1<- 0
1322    b       .LOP_CMPL_FLOAT_finish          @ argh
1323
1324
1325/* ------------------------------ */
1326    .balign 64
1327.L_OP_CMPG_FLOAT: /* 0x2e */
1328/* File: arm-vfp/OP_CMPG_FLOAT.S */
1329    /*
1330     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1331     * destination register based on the results of the comparison.
1332     *
1333     * int compare(x, y) {
1334     *     if (x == y) {
1335     *         return 0;
1336     *     } else if (x < y) {
1337     *         return -1;
1338     *     } else if (x > y) {
1339     *         return 1;
1340     *     } else {
1341     *         return 1;
1342     *     }
1343     * }
1344     */
1345    /* op vAA, vBB, vCC */
1346    FETCH(r0, 1)                        @ r0<- CCBB
1347    mov     r9, rINST, lsr #8           @ r9<- AA
1348    and     r2, r0, #255                @ r2<- BB
1349    mov     r3, r0, lsr #8              @ r3<- CC
1350    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1351    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1352    flds    s0, [r2]                    @ s0<- vBB
1353    flds    s1, [r3]                    @ s1<- vCC
1354    fcmpes  s0, s1                      @ compare (vBB, vCC)
1355    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1356    mov     r0, #1                      @ r0<- 1 (default)
1357    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1358    fmstat                              @ export status flags
1359    mvnmi   r0, #0                      @ (less than) r1<- -1
1360    moveq   r0, #0                      @ (equal) r1<- 0
1361    b       .LOP_CMPG_FLOAT_finish          @ argh
1362
1363
1364/* ------------------------------ */
1365    .balign 64
1366.L_OP_CMPL_DOUBLE: /* 0x2f */
1367/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1368    /*
1369     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1370     * destination register based on the results of the comparison.
1371     *
1372     * int compare(x, y) {
1373     *     if (x == y) {
1374     *         return 0;
1375     *     } else if (x > y) {
1376     *         return 1;
1377     *     } else if (x < y) {
1378     *         return -1;
1379     *     } else {
1380     *         return -1;
1381     *     }
1382     * }
1383     */
1384    /* op vAA, vBB, vCC */
1385    FETCH(r0, 1)                        @ r0<- CCBB
1386    mov     r9, rINST, lsr #8           @ r9<- AA
1387    and     r2, r0, #255                @ r2<- BB
1388    mov     r3, r0, lsr #8              @ r3<- CC
1389    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1390    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1391    fldd    d0, [r2]                    @ d0<- vBB
1392    fldd    d1, [r3]                    @ d1<- vCC
1393    fcmped  d0, d1                      @ compare (vBB, vCC)
1394    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1395    mvn     r0, #0                      @ r0<- -1 (default)
1396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1397    fmstat                              @ export status flags
1398    movgt   r0, #1                      @ (greater than) r1<- 1
1399    moveq   r0, #0                      @ (equal) r1<- 0
1400    b       .LOP_CMPL_DOUBLE_finish          @ argh
1401
1402
1403/* ------------------------------ */
1404    .balign 64
1405.L_OP_CMPG_DOUBLE: /* 0x30 */
1406/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1407    /*
1408     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1409     * destination register based on the results of the comparison.
1410     *
1411     * int compare(x, y) {
1412     *     if (x == y) {
1413     *         return 0;
1414     *     } else if (x < y) {
1415     *         return -1;
1416     *     } else if (x > y) {
1417     *         return 1;
1418     *     } else {
1419     *         return 1;
1420     *     }
1421     * }
1422     */
1423    /* op vAA, vBB, vCC */
1424    FETCH(r0, 1)                        @ r0<- CCBB
1425    mov     r9, rINST, lsr #8           @ r9<- AA
1426    and     r2, r0, #255                @ r2<- BB
1427    mov     r3, r0, lsr #8              @ r3<- CC
1428    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1429    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1430    fldd    d0, [r2]                    @ d0<- vBB
1431    fldd    d1, [r3]                    @ d1<- vCC
1432    fcmped  d0, d1                      @ compare (vBB, vCC)
1433    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1434    mov     r0, #1                      @ r0<- 1 (default)
1435    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1436    fmstat                              @ export status flags
1437    mvnmi   r0, #0                      @ (less than) r1<- -1
1438    moveq   r0, #0                      @ (equal) r1<- 0
1439    b       .LOP_CMPG_DOUBLE_finish          @ argh
1440
1441
1442/* ------------------------------ */
1443    .balign 64
1444.L_OP_CMP_LONG: /* 0x31 */
1445/* File: armv5te/OP_CMP_LONG.S */
1446    /*
1447     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1448     * register based on the results of the comparison.
1449     *
1450     * We load the full values with LDM, but in practice many values could
1451     * be resolved by only looking at the high word.  This could be made
1452     * faster or slower by splitting the LDM into a pair of LDRs.
1453     *
1454     * If we just wanted to set condition flags, we could do this:
1455     *  subs    ip, r0, r2
1456     *  sbcs    ip, r1, r3
1457     *  subeqs  ip, r0, r2
1458     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1459     * integer value, which we can do with 2 conditional mov/mvn instructions
1460     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1461     * us a constant 5-cycle path plus a branch at the end to the
1462     * instruction epilogue code.  The multi-compare approach below needs
1463     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1464     * in the worst case (the 64-bit values are equal).
1465     */
1466    /* cmp-long vAA, vBB, vCC */
1467    FETCH(r0, 1)                        @ r0<- CCBB
1468    mov     r9, rINST, lsr #8           @ r9<- AA
1469    and     r2, r0, #255                @ r2<- BB
1470    mov     r3, r0, lsr #8              @ r3<- CC
1471    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1472    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1473    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1474    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1475    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1476    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1477    bgt     .LOP_CMP_LONG_greater
1478    subs    r1, r0, r2                  @ r1<- r0 - r2
1479    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1480    bne     .LOP_CMP_LONG_less
1481    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1482
1483/* ------------------------------ */
1484    .balign 64
1485.L_OP_IF_EQ: /* 0x32 */
1486/* File: armv6t2/OP_IF_EQ.S */
1487/* File: armv6t2/bincmp.S */
1488    /*
1489     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1490     * fragment that specifies the *reverse* comparison to perform, e.g.
1491     * for "if-le" you would use "gt".
1492     *
1493     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1494     */
1495    /* if-cmp vA, vB, +CCCC */
1496    mov     r1, rINST, lsr #12          @ r1<- B
1497    ubfx    r0, rINST, #8, #4           @ r0<- A
1498    GET_VREG(r3, r1)                    @ r3<- vB
1499    GET_VREG(r2, r0)                    @ r2<- vA
1500    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1501    cmp     r2, r3                      @ compare (vA, vB)
1502    bne  1f                      @ branch to 1 if comparison failed
1503    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1504    movs    r9, r9, asl #1              @ convert to bytes, check sign
1505    bmi     common_backwardBranch       @ yes, do periodic checks
15061:
1507#if defined(WITH_JIT)
1508    GET_JIT_PROF_TABLE(r0)
1509    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1510    b        common_testUpdateProfile
1511#else
1512    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1514    GOTO_OPCODE(ip)                     @ jump to next instruction
1515#endif
1516
1517
1518/* ------------------------------ */
1519    .balign 64
1520.L_OP_IF_NE: /* 0x33 */
1521/* File: armv6t2/OP_IF_NE.S */
1522/* File: armv6t2/bincmp.S */
1523    /*
1524     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1525     * fragment that specifies the *reverse* comparison to perform, e.g.
1526     * for "if-le" you would use "gt".
1527     *
1528     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1529     */
1530    /* if-cmp vA, vB, +CCCC */
1531    mov     r1, rINST, lsr #12          @ r1<- B
1532    ubfx    r0, rINST, #8, #4           @ r0<- A
1533    GET_VREG(r3, r1)                    @ r3<- vB
1534    GET_VREG(r2, r0)                    @ r2<- vA
1535    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1536    cmp     r2, r3                      @ compare (vA, vB)
1537    beq  1f                      @ branch to 1 if comparison failed
1538    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1539    movs    r9, r9, asl #1              @ convert to bytes, check sign
1540    bmi     common_backwardBranch       @ yes, do periodic checks
15411:
1542#if defined(WITH_JIT)
1543    GET_JIT_PROF_TABLE(r0)
1544    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1545    b        common_testUpdateProfile
1546#else
1547    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1549    GOTO_OPCODE(ip)                     @ jump to next instruction
1550#endif
1551
1552
1553/* ------------------------------ */
1554    .balign 64
1555.L_OP_IF_LT: /* 0x34 */
1556/* File: armv6t2/OP_IF_LT.S */
1557/* File: armv6t2/bincmp.S */
1558    /*
1559     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1560     * fragment that specifies the *reverse* comparison to perform, e.g.
1561     * for "if-le" you would use "gt".
1562     *
1563     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1564     */
1565    /* if-cmp vA, vB, +CCCC */
1566    mov     r1, rINST, lsr #12          @ r1<- B
1567    ubfx    r0, rINST, #8, #4           @ r0<- A
1568    GET_VREG(r3, r1)                    @ r3<- vB
1569    GET_VREG(r2, r0)                    @ r2<- vA
1570    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1571    cmp     r2, r3                      @ compare (vA, vB)
1572    bge  1f                      @ branch to 1 if comparison failed
1573    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1574    movs    r9, r9, asl #1              @ convert to bytes, check sign
1575    bmi     common_backwardBranch       @ yes, do periodic checks
15761:
1577#if defined(WITH_JIT)
1578    GET_JIT_PROF_TABLE(r0)
1579    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1580    b        common_testUpdateProfile
1581#else
1582    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1584    GOTO_OPCODE(ip)                     @ jump to next instruction
1585#endif
1586
1587
1588/* ------------------------------ */
1589    .balign 64
1590.L_OP_IF_GE: /* 0x35 */
1591/* File: armv6t2/OP_IF_GE.S */
1592/* File: armv6t2/bincmp.S */
1593    /*
1594     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1595     * fragment that specifies the *reverse* comparison to perform, e.g.
1596     * for "if-le" you would use "gt".
1597     *
1598     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1599     */
1600    /* if-cmp vA, vB, +CCCC */
1601    mov     r1, rINST, lsr #12          @ r1<- B
1602    ubfx    r0, rINST, #8, #4           @ r0<- A
1603    GET_VREG(r3, r1)                    @ r3<- vB
1604    GET_VREG(r2, r0)                    @ r2<- vA
1605    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1606    cmp     r2, r3                      @ compare (vA, vB)
1607    blt  1f                      @ branch to 1 if comparison failed
1608    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1609    movs    r9, r9, asl #1              @ convert to bytes, check sign
1610    bmi     common_backwardBranch       @ yes, do periodic checks
16111:
1612#if defined(WITH_JIT)
1613    GET_JIT_PROF_TABLE(r0)
1614    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1615    b        common_testUpdateProfile
1616#else
1617    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1618    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1619    GOTO_OPCODE(ip)                     @ jump to next instruction
1620#endif
1621
1622
1623/* ------------------------------ */
1624    .balign 64
1625.L_OP_IF_GT: /* 0x36 */
1626/* File: armv6t2/OP_IF_GT.S */
1627/* File: armv6t2/bincmp.S */
1628    /*
1629     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1630     * fragment that specifies the *reverse* comparison to perform, e.g.
1631     * for "if-le" you would use "gt".
1632     *
1633     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1634     */
1635    /* if-cmp vA, vB, +CCCC */
1636    mov     r1, rINST, lsr #12          @ r1<- B
1637    ubfx    r0, rINST, #8, #4           @ r0<- A
1638    GET_VREG(r3, r1)                    @ r3<- vB
1639    GET_VREG(r2, r0)                    @ r2<- vA
1640    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1641    cmp     r2, r3                      @ compare (vA, vB)
1642    ble  1f                      @ branch to 1 if comparison failed
1643    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1644    movs    r9, r9, asl #1              @ convert to bytes, check sign
1645    bmi     common_backwardBranch       @ yes, do periodic checks
16461:
1647#if defined(WITH_JIT)
1648    GET_JIT_PROF_TABLE(r0)
1649    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1650    b        common_testUpdateProfile
1651#else
1652    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1654    GOTO_OPCODE(ip)                     @ jump to next instruction
1655#endif
1656
1657
1658/* ------------------------------ */
1659    .balign 64
1660.L_OP_IF_LE: /* 0x37 */
1661/* File: armv6t2/OP_IF_LE.S */
1662/* File: armv6t2/bincmp.S */
1663    /*
1664     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1665     * fragment that specifies the *reverse* comparison to perform, e.g.
1666     * for "if-le" you would use "gt".
1667     *
1668     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1669     */
1670    /* if-cmp vA, vB, +CCCC */
1671    mov     r1, rINST, lsr #12          @ r1<- B
1672    ubfx    r0, rINST, #8, #4           @ r0<- A
1673    GET_VREG(r3, r1)                    @ r3<- vB
1674    GET_VREG(r2, r0)                    @ r2<- vA
1675    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1676    cmp     r2, r3                      @ compare (vA, vB)
1677    bgt  1f                      @ branch to 1 if comparison failed
1678    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1679    movs    r9, r9, asl #1              @ convert to bytes, check sign
1680    bmi     common_backwardBranch       @ yes, do periodic checks
16811:
1682#if defined(WITH_JIT)
1683    GET_JIT_PROF_TABLE(r0)
1684    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1685    b        common_testUpdateProfile
1686#else
1687    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1689    GOTO_OPCODE(ip)                     @ jump to next instruction
1690#endif
1691
1692
1693/* ------------------------------ */
1694    .balign 64
1695.L_OP_IF_EQZ: /* 0x38 */
1696/* File: armv5te/OP_IF_EQZ.S */
1697/* File: armv5te/zcmp.S */
1698    /*
1699     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1700     * fragment that specifies the *reverse* comparison to perform, e.g.
1701     * for "if-le" you would use "gt".
1702     *
1703     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1704     */
1705    /* if-cmp vAA, +BBBB */
1706    mov     r0, rINST, lsr #8           @ r0<- AA
1707    GET_VREG(r2, r0)                    @ r2<- vAA
1708    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1709    cmp     r2, #0                      @ compare (vA, 0)
1710    bne  1f                      @ branch to 1 if comparison failed
1711    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1712    movs    r9, r9, asl #1              @ convert to bytes, check sign
1713    bmi     common_backwardBranch       @ backward branch, do periodic checks
17141:
1715#if defined(WITH_JIT)
1716    GET_JIT_PROF_TABLE(r0)
1717    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1718    cmp     r0,#0
1719    bne     common_updateProfile
1720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1721    GOTO_OPCODE(ip)                     @ jump to next instruction
1722#else
1723    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1724    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1725    GOTO_OPCODE(ip)                     @ jump to next instruction
1726#endif
1727
1728
1729/* ------------------------------ */
1730    .balign 64
1731.L_OP_IF_NEZ: /* 0x39 */
1732/* File: armv5te/OP_IF_NEZ.S */
1733/* File: armv5te/zcmp.S */
1734    /*
1735     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1736     * fragment that specifies the *reverse* comparison to perform, e.g.
1737     * for "if-le" you would use "gt".
1738     *
1739     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1740     */
1741    /* if-cmp vAA, +BBBB */
1742    mov     r0, rINST, lsr #8           @ r0<- AA
1743    GET_VREG(r2, r0)                    @ r2<- vAA
1744    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1745    cmp     r2, #0                      @ compare (vA, 0)
1746    beq  1f                      @ branch to 1 if comparison failed
1747    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1748    movs    r9, r9, asl #1              @ convert to bytes, check sign
1749    bmi     common_backwardBranch       @ backward branch, do periodic checks
17501:
1751#if defined(WITH_JIT)
1752    GET_JIT_PROF_TABLE(r0)
1753    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1754    cmp     r0,#0
1755    bne     common_updateProfile
1756    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1757    GOTO_OPCODE(ip)                     @ jump to next instruction
1758#else
1759    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1761    GOTO_OPCODE(ip)                     @ jump to next instruction
1762#endif
1763
1764
1765/* ------------------------------ */
1766    .balign 64
1767.L_OP_IF_LTZ: /* 0x3a */
1768/* File: armv5te/OP_IF_LTZ.S */
1769/* File: armv5te/zcmp.S */
1770    /*
1771     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1772     * fragment that specifies the *reverse* comparison to perform, e.g.
1773     * for "if-le" you would use "gt".
1774     *
1775     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1776     */
1777    /* if-cmp vAA, +BBBB */
1778    mov     r0, rINST, lsr #8           @ r0<- AA
1779    GET_VREG(r2, r0)                    @ r2<- vAA
1780    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1781    cmp     r2, #0                      @ compare (vA, 0)
1782    bge  1f                      @ branch to 1 if comparison failed
1783    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1784    movs    r9, r9, asl #1              @ convert to bytes, check sign
1785    bmi     common_backwardBranch       @ backward branch, do periodic checks
17861:
1787#if defined(WITH_JIT)
1788    GET_JIT_PROF_TABLE(r0)
1789    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1790    cmp     r0,#0
1791    bne     common_updateProfile
1792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1793    GOTO_OPCODE(ip)                     @ jump to next instruction
1794#else
1795    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1796    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1797    GOTO_OPCODE(ip)                     @ jump to next instruction
1798#endif
1799
1800
1801/* ------------------------------ */
1802    .balign 64
1803.L_OP_IF_GEZ: /* 0x3b */
1804/* File: armv5te/OP_IF_GEZ.S */
1805/* File: armv5te/zcmp.S */
1806    /*
1807     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1808     * fragment that specifies the *reverse* comparison to perform, e.g.
1809     * for "if-le" you would use "gt".
1810     *
1811     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1812     */
1813    /* if-cmp vAA, +BBBB */
1814    mov     r0, rINST, lsr #8           @ r0<- AA
1815    GET_VREG(r2, r0)                    @ r2<- vAA
1816    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1817    cmp     r2, #0                      @ compare (vA, 0)
1818    blt  1f                      @ branch to 1 if comparison failed
1819    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1820    movs    r9, r9, asl #1              @ convert to bytes, check sign
1821    bmi     common_backwardBranch       @ backward branch, do periodic checks
18221:
1823#if defined(WITH_JIT)
1824    GET_JIT_PROF_TABLE(r0)
1825    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1826    cmp     r0,#0
1827    bne     common_updateProfile
1828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1829    GOTO_OPCODE(ip)                     @ jump to next instruction
1830#else
1831    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1833    GOTO_OPCODE(ip)                     @ jump to next instruction
1834#endif
1835
1836
1837/* ------------------------------ */
1838    .balign 64
1839.L_OP_IF_GTZ: /* 0x3c */
1840/* File: armv5te/OP_IF_GTZ.S */
1841/* File: armv5te/zcmp.S */
1842    /*
1843     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1844     * fragment that specifies the *reverse* comparison to perform, e.g.
1845     * for "if-le" you would use "gt".
1846     *
1847     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1848     */
1849    /* if-cmp vAA, +BBBB */
1850    mov     r0, rINST, lsr #8           @ r0<- AA
1851    GET_VREG(r2, r0)                    @ r2<- vAA
1852    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1853    cmp     r2, #0                      @ compare (vA, 0)
1854    ble  1f                      @ branch to 1 if comparison failed
1855    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1856    movs    r9, r9, asl #1              @ convert to bytes, check sign
1857    bmi     common_backwardBranch       @ backward branch, do periodic checks
18581:
1859#if defined(WITH_JIT)
1860    GET_JIT_PROF_TABLE(r0)
1861    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1862    cmp     r0,#0
1863    bne     common_updateProfile
1864    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1865    GOTO_OPCODE(ip)                     @ jump to next instruction
1866#else
1867    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1868    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1869    GOTO_OPCODE(ip)                     @ jump to next instruction
1870#endif
1871
1872
1873/* ------------------------------ */
1874    .balign 64
1875.L_OP_IF_LEZ: /* 0x3d */
1876/* File: armv5te/OP_IF_LEZ.S */
1877/* File: armv5te/zcmp.S */
1878    /*
1879     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1880     * fragment that specifies the *reverse* comparison to perform, e.g.
1881     * for "if-le" you would use "gt".
1882     *
1883     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1884     */
1885    /* if-cmp vAA, +BBBB */
1886    mov     r0, rINST, lsr #8           @ r0<- AA
1887    GET_VREG(r2, r0)                    @ r2<- vAA
1888    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1889    cmp     r2, #0                      @ compare (vA, 0)
1890    bgt  1f                      @ branch to 1 if comparison failed
1891    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1892    movs    r9, r9, asl #1              @ convert to bytes, check sign
1893    bmi     common_backwardBranch       @ backward branch, do periodic checks
18941:
1895#if defined(WITH_JIT)
1896    GET_JIT_PROF_TABLE(r0)
1897    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1898    cmp     r0,#0
1899    bne     common_updateProfile
1900    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1901    GOTO_OPCODE(ip)                     @ jump to next instruction
1902#else
1903    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1904    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1905    GOTO_OPCODE(ip)                     @ jump to next instruction
1906#endif
1907
1908
1909/* ------------------------------ */
1910    .balign 64
1911.L_OP_UNUSED_3E: /* 0x3e */
1912/* File: armv5te/OP_UNUSED_3E.S */
1913/* File: armv5te/unused.S */
1914    bl      common_abort
1915
1916
1917/* ------------------------------ */
1918    .balign 64
1919.L_OP_UNUSED_3F: /* 0x3f */
1920/* File: armv5te/OP_UNUSED_3F.S */
1921/* File: armv5te/unused.S */
1922    bl      common_abort
1923
1924
1925/* ------------------------------ */
1926    .balign 64
1927.L_OP_UNUSED_40: /* 0x40 */
1928/* File: armv5te/OP_UNUSED_40.S */
1929/* File: armv5te/unused.S */
1930    bl      common_abort
1931
1932
1933/* ------------------------------ */
1934    .balign 64
1935.L_OP_UNUSED_41: /* 0x41 */
1936/* File: armv5te/OP_UNUSED_41.S */
1937/* File: armv5te/unused.S */
1938    bl      common_abort
1939
1940
1941/* ------------------------------ */
1942    .balign 64
1943.L_OP_UNUSED_42: /* 0x42 */
1944/* File: armv5te/OP_UNUSED_42.S */
1945/* File: armv5te/unused.S */
1946    bl      common_abort
1947
1948
1949/* ------------------------------ */
1950    .balign 64
1951.L_OP_UNUSED_43: /* 0x43 */
1952/* File: armv5te/OP_UNUSED_43.S */
1953/* File: armv5te/unused.S */
1954    bl      common_abort
1955
1956
1957/* ------------------------------ */
1958    .balign 64
1959.L_OP_AGET: /* 0x44 */
1960/* File: armv5te/OP_AGET.S */
1961    /*
1962     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1963     *
1964     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1965     * instructions.  We use a pair of FETCH_Bs instead.
1966     *
1967     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1968     */
1969    /* op vAA, vBB, vCC */
1970    FETCH_B(r2, 1, 0)                   @ r2<- BB
1971    mov     r9, rINST, lsr #8           @ r9<- AA
1972    FETCH_B(r3, 1, 1)                   @ r3<- CC
1973    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1974    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1975    cmp     r0, #0                      @ null array object?
1976    beq     common_errNullObject        @ yes, bail
1977    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1978    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1979    cmp     r1, r3                      @ compare unsigned index, length
1980    bcs     common_errArrayIndex        @ index >= length, bail
1981    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1982    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1984    SET_VREG(r2, r9)                    @ vAA<- r2
1985    GOTO_OPCODE(ip)                     @ jump to next instruction
1986
1987/* ------------------------------ */
1988    .balign 64
1989.L_OP_AGET_WIDE: /* 0x45 */
1990/* File: armv5te/OP_AGET_WIDE.S */
1991    /*
1992     * Array get, 64 bits.  vAA <- vBB[vCC].
1993     *
1994     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
1995     */
1996    /* aget-wide vAA, vBB, vCC */
1997    FETCH(r0, 1)                        @ r0<- CCBB
1998    mov     r9, rINST, lsr #8           @ r9<- AA
1999    and     r2, r0, #255                @ r2<- BB
2000    mov     r3, r0, lsr #8              @ r3<- CC
2001    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2002    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2003    cmp     r0, #0                      @ null array object?
2004    beq     common_errNullObject        @ yes, bail
2005    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2006    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2007    cmp     r1, r3                      @ compare unsigned index, length
2008    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2009    b       common_errArrayIndex        @ index >= length, bail
2010    @ May want to swap the order of these two branches depending on how the
2011    @ branch prediction (if any) handles conditional forward branches vs.
2012    @ unconditional forward branches.
2013
2014/* ------------------------------ */
2015    .balign 64
2016.L_OP_AGET_OBJECT: /* 0x46 */
2017/* File: armv5te/OP_AGET_OBJECT.S */
2018/* File: armv5te/OP_AGET.S */
2019    /*
2020     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2021     *
2022     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2023     * instructions.  We use a pair of FETCH_Bs instead.
2024     *
2025     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2026     */
2027    /* op vAA, vBB, vCC */
2028    FETCH_B(r2, 1, 0)                   @ r2<- BB
2029    mov     r9, rINST, lsr #8           @ r9<- AA
2030    FETCH_B(r3, 1, 1)                   @ 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 #2     @ r0<- arrayObj + index*width
2037    cmp     r1, r3                      @ compare unsigned index, length
2038    bcs     common_errArrayIndex        @ index >= length, bail
2039    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2040    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2041    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2042    SET_VREG(r2, r9)                    @ vAA<- r2
2043    GOTO_OPCODE(ip)                     @ jump to next instruction
2044
2045
2046/* ------------------------------ */
2047    .balign 64
2048.L_OP_AGET_BOOLEAN: /* 0x47 */
2049/* File: armv5te/OP_AGET_BOOLEAN.S */
2050/* File: armv5te/OP_AGET.S */
2051    /*
2052     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2053     *
2054     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2055     * instructions.  We use a pair of FETCH_Bs instead.
2056     *
2057     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2058     */
2059    /* op vAA, vBB, vCC */
2060    FETCH_B(r2, 1, 0)                   @ r2<- BB
2061    mov     r9, rINST, lsr #8           @ r9<- AA
2062    FETCH_B(r3, 1, 1)                   @ r3<- CC
2063    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2064    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2065    cmp     r0, #0                      @ null array object?
2066    beq     common_errNullObject        @ yes, bail
2067    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2068    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2069    cmp     r1, r3                      @ compare unsigned index, length
2070    bcs     common_errArrayIndex        @ index >= length, bail
2071    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2072    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2074    SET_VREG(r2, r9)                    @ vAA<- r2
2075    GOTO_OPCODE(ip)                     @ jump to next instruction
2076
2077
2078/* ------------------------------ */
2079    .balign 64
2080.L_OP_AGET_BYTE: /* 0x48 */
2081/* File: armv5te/OP_AGET_BYTE.S */
2082/* File: armv5te/OP_AGET.S */
2083    /*
2084     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2085     *
2086     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2087     * instructions.  We use a pair of FETCH_Bs instead.
2088     *
2089     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2090     */
2091    /* op vAA, vBB, vCC */
2092    FETCH_B(r2, 1, 0)                   @ r2<- BB
2093    mov     r9, rINST, lsr #8           @ r9<- AA
2094    FETCH_B(r3, 1, 1)                   @ r3<- CC
2095    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2096    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2097    cmp     r0, #0                      @ null array object?
2098    beq     common_errNullObject        @ yes, bail
2099    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2100    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2101    cmp     r1, r3                      @ compare unsigned index, length
2102    bcs     common_errArrayIndex        @ index >= length, bail
2103    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2104    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2106    SET_VREG(r2, r9)                    @ vAA<- r2
2107    GOTO_OPCODE(ip)                     @ jump to next instruction
2108
2109
2110/* ------------------------------ */
2111    .balign 64
2112.L_OP_AGET_CHAR: /* 0x49 */
2113/* File: armv5te/OP_AGET_CHAR.S */
2114/* File: armv5te/OP_AGET.S */
2115    /*
2116     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2117     *
2118     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2119     * instructions.  We use a pair of FETCH_Bs instead.
2120     *
2121     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2122     */
2123    /* op vAA, vBB, vCC */
2124    FETCH_B(r2, 1, 0)                   @ r2<- BB
2125    mov     r9, rINST, lsr #8           @ r9<- AA
2126    FETCH_B(r3, 1, 1)                   @ r3<- CC
2127    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2128    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2129    cmp     r0, #0                      @ null array object?
2130    beq     common_errNullObject        @ yes, bail
2131    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2132    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2133    cmp     r1, r3                      @ compare unsigned index, length
2134    bcs     common_errArrayIndex        @ index >= length, bail
2135    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2136    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2137    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2138    SET_VREG(r2, r9)                    @ vAA<- r2
2139    GOTO_OPCODE(ip)                     @ jump to next instruction
2140
2141
2142/* ------------------------------ */
2143    .balign 64
2144.L_OP_AGET_SHORT: /* 0x4a */
2145/* File: armv5te/OP_AGET_SHORT.S */
2146/* File: armv5te/OP_AGET.S */
2147    /*
2148     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2149     *
2150     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2151     * instructions.  We use a pair of FETCH_Bs instead.
2152     *
2153     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2154     */
2155    /* op vAA, vBB, vCC */
2156    FETCH_B(r2, 1, 0)                   @ r2<- BB
2157    mov     r9, rINST, lsr #8           @ r9<- AA
2158    FETCH_B(r3, 1, 1)                   @ r3<- CC
2159    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2160    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2161    cmp     r0, #0                      @ null array object?
2162    beq     common_errNullObject        @ yes, bail
2163    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2164    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2165    cmp     r1, r3                      @ compare unsigned index, length
2166    bcs     common_errArrayIndex        @ index >= length, bail
2167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2168    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2170    SET_VREG(r2, r9)                    @ vAA<- r2
2171    GOTO_OPCODE(ip)                     @ jump to next instruction
2172
2173
2174/* ------------------------------ */
2175    .balign 64
2176.L_OP_APUT: /* 0x4b */
2177/* File: armv5te/OP_APUT.S */
2178    /*
2179     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2180     *
2181     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2182     * instructions.  We use a pair of FETCH_Bs instead.
2183     *
2184     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2185     */
2186    /* op vAA, vBB, vCC */
2187    FETCH_B(r2, 1, 0)                   @ r2<- BB
2188    mov     r9, rINST, lsr #8           @ r9<- AA
2189    FETCH_B(r3, 1, 1)                   @ r3<- CC
2190    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2191    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2192    cmp     r0, #0                      @ null array object?
2193    beq     common_errNullObject        @ yes, bail
2194    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2195    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2196    cmp     r1, r3                      @ compare unsigned index, length
2197    bcs     common_errArrayIndex        @ index >= length, bail
2198    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2199    GET_VREG(r2, r9)                    @ r2<- vAA
2200    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2201    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2202    GOTO_OPCODE(ip)                     @ jump to next instruction
2203
2204/* ------------------------------ */
2205    .balign 64
2206.L_OP_APUT_WIDE: /* 0x4c */
2207/* File: armv5te/OP_APUT_WIDE.S */
2208    /*
2209     * Array put, 64 bits.  vBB[vCC] <- vAA.
2210     *
2211     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2212     */
2213    /* aput-wide vAA, vBB, vCC */
2214    FETCH(r0, 1)                        @ r0<- CCBB
2215    mov     r9, rINST, lsr #8           @ r9<- AA
2216    and     r2, r0, #255                @ r2<- BB
2217    mov     r3, r0, lsr #8              @ r3<- CC
2218    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2219    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2220    cmp     r0, #0                      @ null array object?
2221    beq     common_errNullObject        @ yes, bail
2222    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2223    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2224    cmp     r1, r3                      @ compare unsigned index, length
2225    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2226    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2227    b       common_errArrayIndex        @ index >= length, bail
2228    @ May want to swap the order of these two branches depending on how the
2229    @ branch prediction (if any) handles conditional forward branches vs.
2230    @ unconditional forward branches.
2231
2232/* ------------------------------ */
2233    .balign 64
2234.L_OP_APUT_OBJECT: /* 0x4d */
2235/* File: armv5te/OP_APUT_OBJECT.S */
2236    /*
2237     * Store an object into an array.  vBB[vCC] <- vAA.
2238     */
2239    /* op vAA, vBB, vCC */
2240    FETCH(r0, 1)                        @ r0<- CCBB
2241    mov     r9, rINST, lsr #8           @ r9<- AA
2242    and     r2, r0, #255                @ r2<- BB
2243    mov     r3, r0, lsr #8              @ r3<- CC
2244    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2245    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2246    cmp     rINST, #0                   @ null array object?
2247    GET_VREG(r9, r9)                    @ r9<- vAA
2248    beq     common_errNullObject        @ yes, bail
2249    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2250    add     r10, rINST, r1, lsl #2      @ r10<- arrayObj + index*width
2251    cmp     r1, r3                      @ compare unsigned index, length
2252    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2253    b       common_errArrayIndex        @ index >= length, bail
2254
2255
2256/* ------------------------------ */
2257    .balign 64
2258.L_OP_APUT_BOOLEAN: /* 0x4e */
2259/* File: armv5te/OP_APUT_BOOLEAN.S */
2260/* File: armv5te/OP_APUT.S */
2261    /*
2262     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2263     *
2264     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2265     * instructions.  We use a pair of FETCH_Bs instead.
2266     *
2267     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2268     */
2269    /* op vAA, vBB, vCC */
2270    FETCH_B(r2, 1, 0)                   @ r2<- BB
2271    mov     r9, rINST, lsr #8           @ r9<- AA
2272    FETCH_B(r3, 1, 1)                   @ r3<- CC
2273    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2274    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2275    cmp     r0, #0                      @ null array object?
2276    beq     common_errNullObject        @ yes, bail
2277    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2278    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2279    cmp     r1, r3                      @ compare unsigned index, length
2280    bcs     common_errArrayIndex        @ index >= length, bail
2281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2282    GET_VREG(r2, r9)                    @ r2<- vAA
2283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2284    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2285    GOTO_OPCODE(ip)                     @ jump to next instruction
2286
2287
2288/* ------------------------------ */
2289    .balign 64
2290.L_OP_APUT_BYTE: /* 0x4f */
2291/* File: armv5te/OP_APUT_BYTE.S */
2292/* File: armv5te/OP_APUT.S */
2293    /*
2294     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2295     *
2296     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2297     * instructions.  We use a pair of FETCH_Bs instead.
2298     *
2299     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2300     */
2301    /* op vAA, vBB, vCC */
2302    FETCH_B(r2, 1, 0)                   @ r2<- BB
2303    mov     r9, rINST, lsr #8           @ r9<- AA
2304    FETCH_B(r3, 1, 1)                   @ r3<- CC
2305    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2306    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2307    cmp     r0, #0                      @ null array object?
2308    beq     common_errNullObject        @ yes, bail
2309    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2310    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2311    cmp     r1, r3                      @ compare unsigned index, length
2312    bcs     common_errArrayIndex        @ index >= length, bail
2313    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2314    GET_VREG(r2, r9)                    @ r2<- vAA
2315    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2316    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2317    GOTO_OPCODE(ip)                     @ jump to next instruction
2318
2319
2320/* ------------------------------ */
2321    .balign 64
2322.L_OP_APUT_CHAR: /* 0x50 */
2323/* File: armv5te/OP_APUT_CHAR.S */
2324/* File: armv5te/OP_APUT.S */
2325    /*
2326     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2327     *
2328     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2329     * instructions.  We use a pair of FETCH_Bs instead.
2330     *
2331     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2332     */
2333    /* op vAA, vBB, vCC */
2334    FETCH_B(r2, 1, 0)                   @ r2<- BB
2335    mov     r9, rINST, lsr #8           @ r9<- AA
2336    FETCH_B(r3, 1, 1)                   @ r3<- CC
2337    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2338    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2339    cmp     r0, #0                      @ null array object?
2340    beq     common_errNullObject        @ yes, bail
2341    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2342    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2343    cmp     r1, r3                      @ compare unsigned index, length
2344    bcs     common_errArrayIndex        @ index >= length, bail
2345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2346    GET_VREG(r2, r9)                    @ r2<- vAA
2347    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2348    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2349    GOTO_OPCODE(ip)                     @ jump to next instruction
2350
2351
2352/* ------------------------------ */
2353    .balign 64
2354.L_OP_APUT_SHORT: /* 0x51 */
2355/* File: armv5te/OP_APUT_SHORT.S */
2356/* File: armv5te/OP_APUT.S */
2357    /*
2358     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2359     *
2360     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2361     * instructions.  We use a pair of FETCH_Bs instead.
2362     *
2363     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2364     */
2365    /* op vAA, vBB, vCC */
2366    FETCH_B(r2, 1, 0)                   @ r2<- BB
2367    mov     r9, rINST, lsr #8           @ r9<- AA
2368    FETCH_B(r3, 1, 1)                   @ r3<- CC
2369    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2370    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2371    cmp     r0, #0                      @ null array object?
2372    beq     common_errNullObject        @ yes, bail
2373    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2374    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2375    cmp     r1, r3                      @ compare unsigned index, length
2376    bcs     common_errArrayIndex        @ index >= length, bail
2377    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2378    GET_VREG(r2, r9)                    @ r2<- vAA
2379    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2380    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2381    GOTO_OPCODE(ip)                     @ jump to next instruction
2382
2383
2384/* ------------------------------ */
2385    .balign 64
2386.L_OP_IGET: /* 0x52 */
2387/* File: armv6t2/OP_IGET.S */
2388    /*
2389     * General 32-bit instance field get.
2390     *
2391     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2392     */
2393    /* op vA, vB, field@CCCC */
2394    mov     r0, rINST, lsr #12          @ r0<- B
2395    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2396    FETCH(r1, 1)                        @ r1<- field ref CCCC
2397    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2398    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2399    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2400    cmp     r0, #0                      @ is resolved entry null?
2401    bne     .LOP_IGET_finish          @ no, already resolved
24028:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2403    EXPORT_PC()                         @ resolve() could throw
2404    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2405    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2406    cmp     r0, #0
2407    bne     .LOP_IGET_finish
2408    b       common_exceptionThrown
2409
2410/* ------------------------------ */
2411    .balign 64
2412.L_OP_IGET_WIDE: /* 0x53 */
2413/* File: armv6t2/OP_IGET_WIDE.S */
2414    /*
2415     * Wide 32-bit instance field get.
2416     */
2417    /* iget-wide vA, vB, field@CCCC */
2418    mov     r0, rINST, lsr #12          @ r0<- B
2419    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2420    FETCH(r1, 1)                        @ r1<- field ref CCCC
2421    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2422    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2423    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2424    cmp     r0, #0                      @ is resolved entry null?
2425    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24268:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2427    EXPORT_PC()                         @ resolve() could throw
2428    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2429    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2430    cmp     r0, #0
2431    bne     .LOP_IGET_WIDE_finish
2432    b       common_exceptionThrown
2433
2434/* ------------------------------ */
2435    .balign 64
2436.L_OP_IGET_OBJECT: /* 0x54 */
2437/* File: armv5te/OP_IGET_OBJECT.S */
2438/* File: armv5te/OP_IGET.S */
2439    /*
2440     * General 32-bit instance field get.
2441     *
2442     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2443     */
2444    /* op vA, vB, field@CCCC */
2445    mov     r0, rINST, lsr #12          @ r0<- B
2446    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2447    FETCH(r1, 1)                        @ r1<- field ref CCCC
2448    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2449    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2450    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2451    cmp     r0, #0                      @ is resolved entry null?
2452    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24538:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2454    EXPORT_PC()                         @ resolve() could throw
2455    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2456    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2457    cmp     r0, #0
2458    bne     .LOP_IGET_OBJECT_finish
2459    b       common_exceptionThrown
2460
2461
2462/* ------------------------------ */
2463    .balign 64
2464.L_OP_IGET_BOOLEAN: /* 0x55 */
2465/* File: armv5te/OP_IGET_BOOLEAN.S */
2466@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2467/* File: armv5te/OP_IGET.S */
2468    /*
2469     * General 32-bit instance field get.
2470     *
2471     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2472     */
2473    /* op vA, vB, field@CCCC */
2474    mov     r0, rINST, lsr #12          @ r0<- B
2475    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2476    FETCH(r1, 1)                        @ r1<- field ref CCCC
2477    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2478    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2479    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2480    cmp     r0, #0                      @ is resolved entry null?
2481    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
24828:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2483    EXPORT_PC()                         @ resolve() could throw
2484    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2485    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2486    cmp     r0, #0
2487    bne     .LOP_IGET_BOOLEAN_finish
2488    b       common_exceptionThrown
2489
2490
2491/* ------------------------------ */
2492    .balign 64
2493.L_OP_IGET_BYTE: /* 0x56 */
2494/* File: armv5te/OP_IGET_BYTE.S */
2495@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2496/* File: armv5te/OP_IGET.S */
2497    /*
2498     * General 32-bit instance field get.
2499     *
2500     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2501     */
2502    /* op vA, vB, field@CCCC */
2503    mov     r0, rINST, lsr #12          @ r0<- B
2504    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2505    FETCH(r1, 1)                        @ r1<- field ref CCCC
2506    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2507    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2508    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2509    cmp     r0, #0                      @ is resolved entry null?
2510    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25118:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2512    EXPORT_PC()                         @ resolve() could throw
2513    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2514    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2515    cmp     r0, #0
2516    bne     .LOP_IGET_BYTE_finish
2517    b       common_exceptionThrown
2518
2519
2520/* ------------------------------ */
2521    .balign 64
2522.L_OP_IGET_CHAR: /* 0x57 */
2523/* File: armv5te/OP_IGET_CHAR.S */
2524@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2525/* File: armv5te/OP_IGET.S */
2526    /*
2527     * General 32-bit instance field get.
2528     *
2529     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2530     */
2531    /* op vA, vB, field@CCCC */
2532    mov     r0, rINST, lsr #12          @ r0<- B
2533    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2534    FETCH(r1, 1)                        @ r1<- field ref CCCC
2535    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2536    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2537    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2538    cmp     r0, #0                      @ is resolved entry null?
2539    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25408:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2541    EXPORT_PC()                         @ resolve() could throw
2542    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2543    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2544    cmp     r0, #0
2545    bne     .LOP_IGET_CHAR_finish
2546    b       common_exceptionThrown
2547
2548
2549/* ------------------------------ */
2550    .balign 64
2551.L_OP_IGET_SHORT: /* 0x58 */
2552/* File: armv5te/OP_IGET_SHORT.S */
2553@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2554/* File: armv5te/OP_IGET.S */
2555    /*
2556     * General 32-bit instance field get.
2557     *
2558     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2559     */
2560    /* op vA, vB, field@CCCC */
2561    mov     r0, rINST, lsr #12          @ r0<- B
2562    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2563    FETCH(r1, 1)                        @ r1<- field ref CCCC
2564    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2565    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2566    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2567    cmp     r0, #0                      @ is resolved entry null?
2568    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25698:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2570    EXPORT_PC()                         @ resolve() could throw
2571    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2572    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2573    cmp     r0, #0
2574    bne     .LOP_IGET_SHORT_finish
2575    b       common_exceptionThrown
2576
2577
2578/* ------------------------------ */
2579    .balign 64
2580.L_OP_IPUT: /* 0x59 */
2581/* File: armv6t2/OP_IPUT.S */
2582    /*
2583     * General 32-bit instance field put.
2584     *
2585     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2586     */
2587    /* op vA, vB, field@CCCC */
2588    mov     r0, rINST, lsr #12          @ r0<- B
2589    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2590    FETCH(r1, 1)                        @ r1<- field ref CCCC
2591    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2592    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2593    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2594    cmp     r0, #0                      @ is resolved entry null?
2595    bne     .LOP_IPUT_finish          @ no, already resolved
25968:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2597    EXPORT_PC()                         @ resolve() could throw
2598    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2599    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2600    cmp     r0, #0                      @ success?
2601    bne     .LOP_IPUT_finish          @ yes, finish up
2602    b       common_exceptionThrown
2603
2604/* ------------------------------ */
2605    .balign 64
2606.L_OP_IPUT_WIDE: /* 0x5a */
2607/* File: armv6t2/OP_IPUT_WIDE.S */
2608    /* iput-wide vA, vB, field@CCCC */
2609    mov     r0, rINST, lsr #12          @ r0<- B
2610    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2611    FETCH(r1, 1)                        @ r1<- field ref CCCC
2612    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2613    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2614    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2615    cmp     r0, #0                      @ is resolved entry null?
2616    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26178:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2618    EXPORT_PC()                         @ resolve() could throw
2619    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2620    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2621    cmp     r0, #0                      @ success?
2622    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2623    b       common_exceptionThrown
2624
2625/* ------------------------------ */
2626    .balign 64
2627.L_OP_IPUT_OBJECT: /* 0x5b */
2628/* File: armv5te/OP_IPUT_OBJECT.S */
2629    /*
2630     * 32-bit instance field put.
2631     *
2632     * for: iput-object, iput-object-volatile
2633     */
2634    /* op vA, vB, field@CCCC */
2635    mov     r0, rINST, lsr #12          @ r0<- B
2636    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2637    FETCH(r1, 1)                        @ r1<- field ref CCCC
2638    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2639    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2640    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2641    cmp     r0, #0                      @ is resolved entry null?
2642    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26438:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2644    EXPORT_PC()                         @ resolve() could throw
2645    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2646    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2647    cmp     r0, #0                      @ success?
2648    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2649    b       common_exceptionThrown
2650
2651/* ------------------------------ */
2652    .balign 64
2653.L_OP_IPUT_BOOLEAN: /* 0x5c */
2654/* File: armv5te/OP_IPUT_BOOLEAN.S */
2655@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2656/* File: armv5te/OP_IPUT.S */
2657    /*
2658     * General 32-bit instance field put.
2659     *
2660     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2661     */
2662    /* op vA, vB, field@CCCC */
2663    mov     r0, rINST, lsr #12          @ r0<- B
2664    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2665    FETCH(r1, 1)                        @ r1<- field ref CCCC
2666    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2667    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2668    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2669    cmp     r0, #0                      @ is resolved entry null?
2670    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2672    EXPORT_PC()                         @ resolve() could throw
2673    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2674    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2675    cmp     r0, #0                      @ success?
2676    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2677    b       common_exceptionThrown
2678
2679
2680/* ------------------------------ */
2681    .balign 64
2682.L_OP_IPUT_BYTE: /* 0x5d */
2683/* File: armv5te/OP_IPUT_BYTE.S */
2684@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2685/* File: armv5te/OP_IPUT.S */
2686    /*
2687     * General 32-bit instance field put.
2688     *
2689     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2690     */
2691    /* op vA, vB, field@CCCC */
2692    mov     r0, rINST, lsr #12          @ r0<- B
2693    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2694    FETCH(r1, 1)                        @ r1<- field ref CCCC
2695    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2696    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2697    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2698    cmp     r0, #0                      @ is resolved entry null?
2699    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27008:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2701    EXPORT_PC()                         @ resolve() could throw
2702    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2703    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2704    cmp     r0, #0                      @ success?
2705    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2706    b       common_exceptionThrown
2707
2708
2709/* ------------------------------ */
2710    .balign 64
2711.L_OP_IPUT_CHAR: /* 0x5e */
2712/* File: armv5te/OP_IPUT_CHAR.S */
2713@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2714/* File: armv5te/OP_IPUT.S */
2715    /*
2716     * General 32-bit instance field put.
2717     *
2718     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2719     */
2720    /* op vA, vB, field@CCCC */
2721    mov     r0, rINST, lsr #12          @ r0<- B
2722    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2723    FETCH(r1, 1)                        @ r1<- field ref CCCC
2724    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2725    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2726    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2727    cmp     r0, #0                      @ is resolved entry null?
2728    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2730    EXPORT_PC()                         @ resolve() could throw
2731    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2732    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2733    cmp     r0, #0                      @ success?
2734    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2735    b       common_exceptionThrown
2736
2737
2738/* ------------------------------ */
2739    .balign 64
2740.L_OP_IPUT_SHORT: /* 0x5f */
2741/* File: armv5te/OP_IPUT_SHORT.S */
2742@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2743/* File: armv5te/OP_IPUT.S */
2744    /*
2745     * General 32-bit instance field put.
2746     *
2747     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2748     */
2749    /* op vA, vB, field@CCCC */
2750    mov     r0, rINST, lsr #12          @ r0<- B
2751    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2752    FETCH(r1, 1)                        @ r1<- field ref CCCC
2753    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2754    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2755    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2756    cmp     r0, #0                      @ is resolved entry null?
2757    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2759    EXPORT_PC()                         @ resolve() could throw
2760    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2761    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2762    cmp     r0, #0                      @ success?
2763    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2764    b       common_exceptionThrown
2765
2766
2767/* ------------------------------ */
2768    .balign 64
2769.L_OP_SGET: /* 0x60 */
2770/* File: armv5te/OP_SGET.S */
2771    /*
2772     * General 32-bit SGET handler.
2773     *
2774     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2775     */
2776    /* op vAA, field@BBBB */
2777    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2778    FETCH(r1, 1)                        @ r1<- field ref BBBB
2779    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2780    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2781    cmp     r0, #0                      @ is resolved entry null?
2782    beq     .LOP_SGET_resolve         @ yes, do resolve
2783.LOP_SGET_finish: @ field ptr in r0
2784    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2785    @ no-op                             @ acquiring load
2786    mov     r2, rINST, lsr #8           @ r2<- AA
2787    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2788    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2790    GOTO_OPCODE(ip)                     @ jump to next instruction
2791
2792/* ------------------------------ */
2793    .balign 64
2794.L_OP_SGET_WIDE: /* 0x61 */
2795/* File: armv5te/OP_SGET_WIDE.S */
2796    /*
2797     * 64-bit SGET handler.
2798     */
2799    /* sget-wide vAA, field@BBBB */
2800    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2801    FETCH(r1, 1)                        @ r1<- field ref BBBB
2802    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2803    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2804    cmp     r0, #0                      @ is resolved entry null?
2805    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2806.LOP_SGET_WIDE_finish:
2807    mov     r9, rINST, lsr #8           @ r9<- AA
2808    .if 0
2809    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2810    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2811    .else
2812    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2813    .endif
2814    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2815    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2816    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2817    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2818    GOTO_OPCODE(ip)                     @ jump to next instruction
2819
2820/* ------------------------------ */
2821    .balign 64
2822.L_OP_SGET_OBJECT: /* 0x62 */
2823/* File: armv5te/OP_SGET_OBJECT.S */
2824/* File: armv5te/OP_SGET.S */
2825    /*
2826     * General 32-bit SGET handler.
2827     *
2828     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2829     */
2830    /* op vAA, field@BBBB */
2831    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2832    FETCH(r1, 1)                        @ r1<- field ref BBBB
2833    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2834    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2835    cmp     r0, #0                      @ is resolved entry null?
2836    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2837.LOP_SGET_OBJECT_finish: @ field ptr in r0
2838    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2839    @ no-op                             @ acquiring load
2840    mov     r2, rINST, lsr #8           @ r2<- AA
2841    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2842    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2844    GOTO_OPCODE(ip)                     @ jump to next instruction
2845
2846
2847/* ------------------------------ */
2848    .balign 64
2849.L_OP_SGET_BOOLEAN: /* 0x63 */
2850/* File: armv5te/OP_SGET_BOOLEAN.S */
2851/* File: armv5te/OP_SGET.S */
2852    /*
2853     * General 32-bit SGET handler.
2854     *
2855     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2856     */
2857    /* op vAA, field@BBBB */
2858    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2859    FETCH(r1, 1)                        @ r1<- field ref BBBB
2860    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2861    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2862    cmp     r0, #0                      @ is resolved entry null?
2863    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2864.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2865    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2866    @ no-op                             @ acquiring load
2867    mov     r2, rINST, lsr #8           @ r2<- AA
2868    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2869    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2871    GOTO_OPCODE(ip)                     @ jump to next instruction
2872
2873
2874/* ------------------------------ */
2875    .balign 64
2876.L_OP_SGET_BYTE: /* 0x64 */
2877/* File: armv5te/OP_SGET_BYTE.S */
2878/* File: armv5te/OP_SGET.S */
2879    /*
2880     * General 32-bit SGET handler.
2881     *
2882     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2883     */
2884    /* op vAA, field@BBBB */
2885    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2886    FETCH(r1, 1)                        @ r1<- field ref BBBB
2887    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2888    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2889    cmp     r0, #0                      @ is resolved entry null?
2890    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2891.LOP_SGET_BYTE_finish: @ field ptr in r0
2892    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2893    @ no-op                             @ acquiring load
2894    mov     r2, rINST, lsr #8           @ r2<- AA
2895    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2896    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2898    GOTO_OPCODE(ip)                     @ jump to next instruction
2899
2900
2901/* ------------------------------ */
2902    .balign 64
2903.L_OP_SGET_CHAR: /* 0x65 */
2904/* File: armv5te/OP_SGET_CHAR.S */
2905/* File: armv5te/OP_SGET.S */
2906    /*
2907     * General 32-bit SGET handler.
2908     *
2909     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2910     */
2911    /* op vAA, field@BBBB */
2912    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2913    FETCH(r1, 1)                        @ r1<- field ref BBBB
2914    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2915    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2916    cmp     r0, #0                      @ is resolved entry null?
2917    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2918.LOP_SGET_CHAR_finish: @ field ptr in r0
2919    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2920    @ no-op                             @ acquiring load
2921    mov     r2, rINST, lsr #8           @ r2<- AA
2922    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2923    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2925    GOTO_OPCODE(ip)                     @ jump to next instruction
2926
2927
2928/* ------------------------------ */
2929    .balign 64
2930.L_OP_SGET_SHORT: /* 0x66 */
2931/* File: armv5te/OP_SGET_SHORT.S */
2932/* File: armv5te/OP_SGET.S */
2933    /*
2934     * General 32-bit SGET handler.
2935     *
2936     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2937     */
2938    /* op vAA, field@BBBB */
2939    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2940    FETCH(r1, 1)                        @ r1<- field ref BBBB
2941    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2942    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2943    cmp     r0, #0                      @ is resolved entry null?
2944    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2945.LOP_SGET_SHORT_finish: @ field ptr in r0
2946    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2947    @ no-op                             @ acquiring load
2948    mov     r2, rINST, lsr #8           @ r2<- AA
2949    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2950    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2952    GOTO_OPCODE(ip)                     @ jump to next instruction
2953
2954
2955/* ------------------------------ */
2956    .balign 64
2957.L_OP_SPUT: /* 0x67 */
2958/* File: armv5te/OP_SPUT.S */
2959    /*
2960     * General 32-bit SPUT handler.
2961     *
2962     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2963     */
2964    /* op vAA, field@BBBB */
2965    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2966    FETCH(r1, 1)                        @ r1<- field ref BBBB
2967    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2968    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2969    cmp     r0, #0                      @ is resolved entry null?
2970    beq     .LOP_SPUT_resolve         @ yes, do resolve
2971.LOP_SPUT_finish:   @ field ptr in r0
2972    mov     r2, rINST, lsr #8           @ r2<- AA
2973    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2974    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2975    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2976    @ no-op                             @ releasing store
2977    str     r1, [r0, #offStaticField_value] @ field<- vAA
2978    GOTO_OPCODE(ip)                     @ jump to next instruction
2979
2980/* ------------------------------ */
2981    .balign 64
2982.L_OP_SPUT_WIDE: /* 0x68 */
2983/* File: armv5te/OP_SPUT_WIDE.S */
2984    /*
2985     * 64-bit SPUT handler.
2986     */
2987    /* sput-wide vAA, field@BBBB */
2988    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
2989    FETCH(r1, 1)                        @ r1<- field ref BBBB
2990    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
2991    mov     r9, rINST, lsr #8           @ r9<- AA
2992    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
2993    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2994    cmp     r2, #0                      @ is resolved entry null?
2995    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
2996.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
2997    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2998    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
2999    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3000    .if 0
3001    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3002    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3003    .else
3004    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3005    .endif
3006    GOTO_OPCODE(r10)                    @ jump to next instruction
3007
3008/* ------------------------------ */
3009    .balign 64
3010.L_OP_SPUT_OBJECT: /* 0x69 */
3011/* File: armv5te/OP_SPUT_OBJECT.S */
3012    /*
3013     * 32-bit SPUT handler for objects
3014     *
3015     * for: sput-object, sput-object-volatile
3016     */
3017    /* op vAA, field@BBBB */
3018    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3019    FETCH(r1, 1)                        @ r1<- field ref BBBB
3020    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3021    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3022    cmp     r0, #0                      @ is resolved entry null?
3023    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3024    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3025    EXPORT_PC()                         @ resolve() could throw, so export now
3026    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3027    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3028    cmp     r0, #0                      @ success?
3029    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3030    b       common_exceptionThrown      @ no, handle exception
3031
3032
3033/* ------------------------------ */
3034    .balign 64
3035.L_OP_SPUT_BOOLEAN: /* 0x6a */
3036/* File: armv5te/OP_SPUT_BOOLEAN.S */
3037/* File: armv5te/OP_SPUT.S */
3038    /*
3039     * General 32-bit SPUT handler.
3040     *
3041     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3042     */
3043    /* op vAA, field@BBBB */
3044    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3045    FETCH(r1, 1)                        @ r1<- field ref BBBB
3046    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3047    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3048    cmp     r0, #0                      @ is resolved entry null?
3049    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3050.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3051    mov     r2, rINST, lsr #8           @ r2<- AA
3052    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3053    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3054    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3055    @ no-op                             @ releasing store
3056    str     r1, [r0, #offStaticField_value] @ field<- vAA
3057    GOTO_OPCODE(ip)                     @ jump to next instruction
3058
3059
3060/* ------------------------------ */
3061    .balign 64
3062.L_OP_SPUT_BYTE: /* 0x6b */
3063/* File: armv5te/OP_SPUT_BYTE.S */
3064/* File: armv5te/OP_SPUT.S */
3065    /*
3066     * General 32-bit SPUT handler.
3067     *
3068     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3069     */
3070    /* op vAA, field@BBBB */
3071    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3072    FETCH(r1, 1)                        @ r1<- field ref BBBB
3073    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3074    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3075    cmp     r0, #0                      @ is resolved entry null?
3076    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3077.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3078    mov     r2, rINST, lsr #8           @ r2<- AA
3079    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3080    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3082    @ no-op                             @ releasing store
3083    str     r1, [r0, #offStaticField_value] @ field<- vAA
3084    GOTO_OPCODE(ip)                     @ jump to next instruction
3085
3086
3087/* ------------------------------ */
3088    .balign 64
3089.L_OP_SPUT_CHAR: /* 0x6c */
3090/* File: armv5te/OP_SPUT_CHAR.S */
3091/* File: armv5te/OP_SPUT.S */
3092    /*
3093     * General 32-bit SPUT handler.
3094     *
3095     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3096     */
3097    /* op vAA, field@BBBB */
3098    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3099    FETCH(r1, 1)                        @ r1<- field ref BBBB
3100    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3101    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3102    cmp     r0, #0                      @ is resolved entry null?
3103    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3104.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3105    mov     r2, rINST, lsr #8           @ r2<- AA
3106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3107    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3108    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3109    @ no-op                             @ releasing store
3110    str     r1, [r0, #offStaticField_value] @ field<- vAA
3111    GOTO_OPCODE(ip)                     @ jump to next instruction
3112
3113
3114/* ------------------------------ */
3115    .balign 64
3116.L_OP_SPUT_SHORT: /* 0x6d */
3117/* File: armv5te/OP_SPUT_SHORT.S */
3118/* File: armv5te/OP_SPUT.S */
3119    /*
3120     * General 32-bit SPUT handler.
3121     *
3122     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3123     */
3124    /* op vAA, field@BBBB */
3125    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3126    FETCH(r1, 1)                        @ r1<- field ref BBBB
3127    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3128    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3129    cmp     r0, #0                      @ is resolved entry null?
3130    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3131.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3132    mov     r2, rINST, lsr #8           @ r2<- AA
3133    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3134    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3135    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3136    @ no-op                             @ releasing store
3137    str     r1, [r0, #offStaticField_value] @ field<- vAA
3138    GOTO_OPCODE(ip)                     @ jump to next instruction
3139
3140
3141/* ------------------------------ */
3142    .balign 64
3143.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3144/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3145    /*
3146     * Handle a virtual method call.
3147     *
3148     * for: invoke-virtual, invoke-virtual/range
3149     */
3150    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3151    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3152    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3153    FETCH(r1, 1)                        @ r1<- BBBB
3154    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3155    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3156    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3157    .if     (!0)
3158    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3159    .endif
3160    cmp     r0, #0                      @ already resolved?
3161    EXPORT_PC()                         @ must export for invoke
3162    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3163    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3164    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3165    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3166    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3167    cmp     r0, #0                      @ got null?
3168    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3169    b       common_exceptionThrown      @ yes, handle exception
3170
3171/* ------------------------------ */
3172    .balign 64
3173.L_OP_INVOKE_SUPER: /* 0x6f */
3174/* File: armv5te/OP_INVOKE_SUPER.S */
3175    /*
3176     * Handle a "super" method call.
3177     *
3178     * for: invoke-super, invoke-super/range
3179     */
3180    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3181    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3182    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3183    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3184    .if     (!0)
3185    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3186    .endif
3187    FETCH(r1, 1)                        @ r1<- BBBB
3188    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3189    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3190    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3191    cmp     r2, #0                      @ null "this"?
3192    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3193    beq     common_errNullObject        @ null "this", throw exception
3194    cmp     r0, #0                      @ already resolved?
3195    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3196    EXPORT_PC()                         @ must export for invoke
3197    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3198    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3199
3200/* ------------------------------ */
3201    .balign 64
3202.L_OP_INVOKE_DIRECT: /* 0x70 */
3203/* File: armv5te/OP_INVOKE_DIRECT.S */
3204    /*
3205     * Handle a direct method call.
3206     *
3207     * (We could defer the "is 'this' pointer null" test to the common
3208     * method invocation code, and use a flag to indicate that static
3209     * calls don't count.  If we do this as part of copying the arguments
3210     * out we could avoiding loading the first arg twice.)
3211     *
3212     * for: invoke-direct, invoke-direct/range
3213     */
3214    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3215    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3216    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3217    FETCH(r1, 1)                        @ r1<- BBBB
3218    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3219    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3220    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3221    .if     (!0)
3222    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3223    .endif
3224    cmp     r0, #0                      @ already resolved?
3225    EXPORT_PC()                         @ must export for invoke
3226    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3227    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3228.LOP_INVOKE_DIRECT_finish:
3229    cmp     r2, #0                      @ null "this" ref?
3230    bne     common_invokeMethodNoRange   @ no, continue on
3231    b       common_errNullObject        @ yes, throw exception
3232
3233/* ------------------------------ */
3234    .balign 64
3235.L_OP_INVOKE_STATIC: /* 0x71 */
3236/* File: armv5te/OP_INVOKE_STATIC.S */
3237    /*
3238     * Handle a static method call.
3239     *
3240     * for: invoke-static, invoke-static/range
3241     */
3242    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3243    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3244    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3245    FETCH(r1, 1)                        @ r1<- BBBB
3246    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3247    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3248    cmp     r0, #0                      @ already resolved?
3249    EXPORT_PC()                         @ must export for invoke
3250    bne     common_invokeMethodNoRange @ yes, continue on
32510:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3252    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3253    mov     r2, #METHOD_STATIC          @ resolver method type
3254    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3255    cmp     r0, #0                      @ got null?
3256    bne     common_invokeMethodNoRange @ no, continue
3257    b       common_exceptionThrown      @ yes, handle exception
3258
3259/* ------------------------------ */
3260    .balign 64
3261.L_OP_INVOKE_INTERFACE: /* 0x72 */
3262/* File: armv5te/OP_INVOKE_INTERFACE.S */
3263    /*
3264     * Handle an interface method call.
3265     *
3266     * for: invoke-interface, invoke-interface/range
3267     */
3268    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3269    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3270    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3271    FETCH(r1, 1)                        @ r1<- BBBB
3272    .if     (!0)
3273    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3274    .endif
3275    EXPORT_PC()                         @ must export for invoke
3276    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3277    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3278    cmp     r0, #0                      @ null obj?
3279    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3280    beq     common_errNullObject        @ yes, fail
3281    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3282    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3283    cmp     r0, #0                      @ failed?
3284    beq     common_exceptionThrown      @ yes, handle exception
3285    b       common_invokeMethodNoRange @ jump to common handler
3286
3287/* ------------------------------ */
3288    .balign 64
3289.L_OP_UNUSED_73: /* 0x73 */
3290/* File: armv5te/OP_UNUSED_73.S */
3291/* File: armv5te/unused.S */
3292    bl      common_abort
3293
3294
3295/* ------------------------------ */
3296    .balign 64
3297.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3298/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3299/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3300    /*
3301     * Handle a virtual method call.
3302     *
3303     * for: invoke-virtual, invoke-virtual/range
3304     */
3305    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3306    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3307    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3308    FETCH(r1, 1)                        @ r1<- BBBB
3309    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3310    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3311    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3312    .if     (!1)
3313    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3314    .endif
3315    cmp     r0, #0                      @ already resolved?
3316    EXPORT_PC()                         @ must export for invoke
3317    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3318    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3319    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3320    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3321    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3322    cmp     r0, #0                      @ got null?
3323    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3324    b       common_exceptionThrown      @ yes, handle exception
3325
3326
3327/* ------------------------------ */
3328    .balign 64
3329.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3330/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3331/* File: armv5te/OP_INVOKE_SUPER.S */
3332    /*
3333     * Handle a "super" method call.
3334     *
3335     * for: invoke-super, invoke-super/range
3336     */
3337    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3338    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3339    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3340    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3341    .if     (!1)
3342    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3343    .endif
3344    FETCH(r1, 1)                        @ r1<- BBBB
3345    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3346    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3347    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3348    cmp     r2, #0                      @ null "this"?
3349    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3350    beq     common_errNullObject        @ null "this", throw exception
3351    cmp     r0, #0                      @ already resolved?
3352    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3353    EXPORT_PC()                         @ must export for invoke
3354    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3355    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3356
3357
3358/* ------------------------------ */
3359    .balign 64
3360.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3361/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3362/* File: armv5te/OP_INVOKE_DIRECT.S */
3363    /*
3364     * Handle a direct method call.
3365     *
3366     * (We could defer the "is 'this' pointer null" test to the common
3367     * method invocation code, and use a flag to indicate that static
3368     * calls don't count.  If we do this as part of copying the arguments
3369     * out we could avoiding loading the first arg twice.)
3370     *
3371     * for: invoke-direct, invoke-direct/range
3372     */
3373    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3374    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3375    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3376    FETCH(r1, 1)                        @ r1<- BBBB
3377    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3378    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3379    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3380    .if     (!1)
3381    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3382    .endif
3383    cmp     r0, #0                      @ already resolved?
3384    EXPORT_PC()                         @ must export for invoke
3385    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3386    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3387.LOP_INVOKE_DIRECT_RANGE_finish:
3388    cmp     r2, #0                      @ null "this" ref?
3389    bne     common_invokeMethodRange   @ no, continue on
3390    b       common_errNullObject        @ yes, throw exception
3391
3392
3393/* ------------------------------ */
3394    .balign 64
3395.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3396/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3397/* File: armv5te/OP_INVOKE_STATIC.S */
3398    /*
3399     * Handle a static method call.
3400     *
3401     * for: invoke-static, invoke-static/range
3402     */
3403    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3404    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3405    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3406    FETCH(r1, 1)                        @ r1<- BBBB
3407    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3408    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3409    cmp     r0, #0                      @ already resolved?
3410    EXPORT_PC()                         @ must export for invoke
3411    bne     common_invokeMethodRange @ yes, continue on
34120:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3413    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3414    mov     r2, #METHOD_STATIC          @ resolver method type
3415    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3416    cmp     r0, #0                      @ got null?
3417    bne     common_invokeMethodRange @ no, continue
3418    b       common_exceptionThrown      @ yes, handle exception
3419
3420
3421/* ------------------------------ */
3422    .balign 64
3423.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3424/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3425/* File: armv5te/OP_INVOKE_INTERFACE.S */
3426    /*
3427     * Handle an interface method call.
3428     *
3429     * for: invoke-interface, invoke-interface/range
3430     */
3431    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3432    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3433    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3434    FETCH(r1, 1)                        @ r1<- BBBB
3435    .if     (!1)
3436    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3437    .endif
3438    EXPORT_PC()                         @ must export for invoke
3439    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3440    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3441    cmp     r0, #0                      @ null obj?
3442    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3443    beq     common_errNullObject        @ yes, fail
3444    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3445    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3446    cmp     r0, #0                      @ failed?
3447    beq     common_exceptionThrown      @ yes, handle exception
3448    b       common_invokeMethodRange @ jump to common handler
3449
3450
3451/* ------------------------------ */
3452    .balign 64
3453.L_OP_UNUSED_79: /* 0x79 */
3454/* File: armv5te/OP_UNUSED_79.S */
3455/* File: armv5te/unused.S */
3456    bl      common_abort
3457
3458
3459/* ------------------------------ */
3460    .balign 64
3461.L_OP_UNUSED_7A: /* 0x7a */
3462/* File: armv5te/OP_UNUSED_7A.S */
3463/* File: armv5te/unused.S */
3464    bl      common_abort
3465
3466
3467/* ------------------------------ */
3468    .balign 64
3469.L_OP_NEG_INT: /* 0x7b */
3470/* File: armv6t2/OP_NEG_INT.S */
3471/* File: armv6t2/unop.S */
3472    /*
3473     * Generic 32-bit unary operation.  Provide an "instr" line that
3474     * specifies an instruction that performs "result = op r0".
3475     * This could be an ARM instruction or a function call.
3476     *
3477     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3478     *      int-to-byte, int-to-char, int-to-short
3479     */
3480    /* unop vA, vB */
3481    mov     r3, rINST, lsr #12          @ r3<- B
3482    ubfx    r9, rINST, #8, #4           @ r9<- A
3483    GET_VREG(r0, r3)                    @ r0<- vB
3484                               @ optional op; may set condition codes
3485    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3486    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3488    SET_VREG(r0, r9)                    @ vAA<- r0
3489    GOTO_OPCODE(ip)                     @ jump to next instruction
3490    /* 8-9 instructions */
3491
3492
3493/* ------------------------------ */
3494    .balign 64
3495.L_OP_NOT_INT: /* 0x7c */
3496/* File: armv6t2/OP_NOT_INT.S */
3497/* File: armv6t2/unop.S */
3498    /*
3499     * Generic 32-bit unary operation.  Provide an "instr" line that
3500     * specifies an instruction that performs "result = op r0".
3501     * This could be an ARM instruction or a function call.
3502     *
3503     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3504     *      int-to-byte, int-to-char, int-to-short
3505     */
3506    /* unop vA, vB */
3507    mov     r3, rINST, lsr #12          @ r3<- B
3508    ubfx    r9, rINST, #8, #4           @ r9<- A
3509    GET_VREG(r0, r3)                    @ r0<- vB
3510                               @ optional op; may set condition codes
3511    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3512    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3514    SET_VREG(r0, r9)                    @ vAA<- r0
3515    GOTO_OPCODE(ip)                     @ jump to next instruction
3516    /* 8-9 instructions */
3517
3518
3519/* ------------------------------ */
3520    .balign 64
3521.L_OP_NEG_LONG: /* 0x7d */
3522/* File: armv6t2/OP_NEG_LONG.S */
3523/* File: armv6t2/unopWide.S */
3524    /*
3525     * Generic 64-bit unary operation.  Provide an "instr" line that
3526     * specifies an instruction that performs "result = op r0/r1".
3527     * This could be an ARM instruction or a function call.
3528     *
3529     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3530     */
3531    /* unop vA, vB */
3532    mov     r3, rINST, lsr #12          @ r3<- B
3533    ubfx    r9, rINST, #8, #4           @ r9<- A
3534    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3535    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3536    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3537    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3538    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3539    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3541    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3542    GOTO_OPCODE(ip)                     @ jump to next instruction
3543    /* 10-11 instructions */
3544
3545
3546/* ------------------------------ */
3547    .balign 64
3548.L_OP_NOT_LONG: /* 0x7e */
3549/* File: armv6t2/OP_NOT_LONG.S */
3550/* File: armv6t2/unopWide.S */
3551    /*
3552     * Generic 64-bit unary operation.  Provide an "instr" line that
3553     * specifies an instruction that performs "result = op r0/r1".
3554     * This could be an ARM instruction or a function call.
3555     *
3556     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3557     */
3558    /* unop vA, vB */
3559    mov     r3, rINST, lsr #12          @ r3<- B
3560    ubfx    r9, rINST, #8, #4           @ r9<- A
3561    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3562    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3563    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3564    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3565    mvn     r0, r0                           @ optional op; may set condition codes
3566    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3568    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3569    GOTO_OPCODE(ip)                     @ jump to next instruction
3570    /* 10-11 instructions */
3571
3572
3573/* ------------------------------ */
3574    .balign 64
3575.L_OP_NEG_FLOAT: /* 0x7f */
3576/* File: armv6t2/OP_NEG_FLOAT.S */
3577/* File: armv6t2/unop.S */
3578    /*
3579     * Generic 32-bit unary operation.  Provide an "instr" line that
3580     * specifies an instruction that performs "result = op r0".
3581     * This could be an ARM instruction or a function call.
3582     *
3583     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3584     *      int-to-byte, int-to-char, int-to-short
3585     */
3586    /* unop vA, vB */
3587    mov     r3, rINST, lsr #12          @ r3<- B
3588    ubfx    r9, rINST, #8, #4           @ r9<- A
3589    GET_VREG(r0, r3)                    @ r0<- vB
3590                               @ optional op; may set condition codes
3591    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3592    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3593    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3594    SET_VREG(r0, r9)                    @ vAA<- r0
3595    GOTO_OPCODE(ip)                     @ jump to next instruction
3596    /* 8-9 instructions */
3597
3598
3599/* ------------------------------ */
3600    .balign 64
3601.L_OP_NEG_DOUBLE: /* 0x80 */
3602/* File: armv6t2/OP_NEG_DOUBLE.S */
3603/* File: armv6t2/unopWide.S */
3604    /*
3605     * Generic 64-bit unary operation.  Provide an "instr" line that
3606     * specifies an instruction that performs "result = op r0/r1".
3607     * This could be an ARM instruction or a function call.
3608     *
3609     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3610     */
3611    /* unop vA, vB */
3612    mov     r3, rINST, lsr #12          @ r3<- B
3613    ubfx    r9, rINST, #8, #4           @ r9<- A
3614    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3615    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3616    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3617    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3618                               @ optional op; may set condition codes
3619    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3620    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3621    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3622    GOTO_OPCODE(ip)                     @ jump to next instruction
3623    /* 10-11 instructions */
3624
3625
3626/* ------------------------------ */
3627    .balign 64
3628.L_OP_INT_TO_LONG: /* 0x81 */
3629/* File: armv6t2/OP_INT_TO_LONG.S */
3630/* File: armv6t2/unopWider.S */
3631    /*
3632     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3633     * that specifies an instruction that performs "result = op r0", where
3634     * "result" is a 64-bit quantity in r0/r1.
3635     *
3636     * For: int-to-long, int-to-double, float-to-long, float-to-double
3637     */
3638    /* unop vA, vB */
3639    mov     r3, rINST, lsr #12          @ r3<- B
3640    ubfx    r9, rINST, #8, #4           @ r9<- A
3641    GET_VREG(r0, r3)                    @ r0<- vB
3642    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3643                               @ optional op; may set condition codes
3644    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3645    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3646    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3647    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3648    GOTO_OPCODE(ip)                     @ jump to next instruction
3649    /* 9-10 instructions */
3650
3651
3652/* ------------------------------ */
3653    .balign 64
3654.L_OP_INT_TO_FLOAT: /* 0x82 */
3655/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3656/* File: arm-vfp/funop.S */
3657    /*
3658     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3659     * line that specifies an instruction that performs "s1 = op s0".
3660     *
3661     * for: int-to-float, float-to-int
3662     */
3663    /* unop vA, vB */
3664    mov     r3, rINST, lsr #12          @ r3<- B
3665    mov     r9, rINST, lsr #8           @ r9<- A+
3666    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3667    flds    s0, [r3]                    @ s0<- vB
3668    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3669    and     r9, r9, #15                 @ r9<- A
3670    fsitos  s1, s0                              @ s1<- op
3671    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3672    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3673    fsts    s1, [r9]                    @ vA<- s1
3674    GOTO_OPCODE(ip)                     @ jump to next instruction
3675
3676
3677/* ------------------------------ */
3678    .balign 64
3679.L_OP_INT_TO_DOUBLE: /* 0x83 */
3680/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3681/* File: arm-vfp/funopWider.S */
3682    /*
3683     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3684     * "instr" line that specifies an instruction that performs "d0 = op s0".
3685     *
3686     * For: int-to-double, float-to-double
3687     */
3688    /* unop vA, vB */
3689    mov     r3, rINST, lsr #12          @ r3<- B
3690    mov     r9, rINST, lsr #8           @ r9<- A+
3691    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3692    flds    s0, [r3]                    @ s0<- vB
3693    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3694    and     r9, r9, #15                 @ r9<- A
3695    fsitod  d0, s0                              @ d0<- op
3696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3697    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3698    fstd    d0, [r9]                    @ vA<- d0
3699    GOTO_OPCODE(ip)                     @ jump to next instruction
3700
3701
3702/* ------------------------------ */
3703    .balign 64
3704.L_OP_LONG_TO_INT: /* 0x84 */
3705/* File: armv5te/OP_LONG_TO_INT.S */
3706/* we ignore the high word, making this equivalent to a 32-bit reg move */
3707/* File: armv5te/OP_MOVE.S */
3708    /* for move, move-object, long-to-int */
3709    /* op vA, vB */
3710    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3711    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3712    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3713    GET_VREG(r2, r1)                    @ r2<- fp[B]
3714    and     r0, r0, #15
3715    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3716    SET_VREG(r2, r0)                    @ fp[A]<- r2
3717    GOTO_OPCODE(ip)                     @ execute next instruction
3718
3719
3720/* ------------------------------ */
3721    .balign 64
3722.L_OP_LONG_TO_FLOAT: /* 0x85 */
3723/* File: armv6t2/OP_LONG_TO_FLOAT.S */
3724/* File: armv6t2/unopNarrower.S */
3725    /*
3726     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3727     * that specifies an instruction that performs "result = op r0/r1", where
3728     * "result" is a 32-bit quantity in r0.
3729     *
3730     * For: long-to-float, double-to-int, double-to-float
3731     *
3732     * (This would work for long-to-int, but that instruction is actually
3733     * an exact match for OP_MOVE.)
3734     */
3735    /* unop vA, vB */
3736    mov     r3, rINST, lsr #12          @ r3<- B
3737    ubfx    r9, rINST, #8, #4           @ r9<- A
3738    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3739    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3740    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3741                               @ optional op; may set condition codes
3742    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3744    SET_VREG(r0, r9)                    @ vA<- r0
3745    GOTO_OPCODE(ip)                     @ jump to next instruction
3746    /* 9-10 instructions */
3747
3748
3749/* ------------------------------ */
3750    .balign 64
3751.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3752/* File: armv6t2/OP_LONG_TO_DOUBLE.S */
3753/* File: armv6t2/unopWide.S */
3754    /*
3755     * Generic 64-bit unary operation.  Provide an "instr" line that
3756     * specifies an instruction that performs "result = op r0/r1".
3757     * This could be an ARM instruction or a function call.
3758     *
3759     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3760     */
3761    /* unop vA, vB */
3762    mov     r3, rINST, lsr #12          @ r3<- B
3763    ubfx    r9, rINST, #8, #4           @ r9<- A
3764    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3765    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3766    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3767    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3768                               @ optional op; may set condition codes
3769    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3770    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3771    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3772    GOTO_OPCODE(ip)                     @ jump to next instruction
3773    /* 10-11 instructions */
3774
3775
3776/* ------------------------------ */
3777    .balign 64
3778.L_OP_FLOAT_TO_INT: /* 0x87 */
3779/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3780/* File: arm-vfp/funop.S */
3781    /*
3782     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3783     * line that specifies an instruction that performs "s1 = op s0".
3784     *
3785     * for: int-to-float, float-to-int
3786     */
3787    /* unop vA, vB */
3788    mov     r3, rINST, lsr #12          @ r3<- B
3789    mov     r9, rINST, lsr #8           @ r9<- A+
3790    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3791    flds    s0, [r3]                    @ s0<- vB
3792    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3793    and     r9, r9, #15                 @ r9<- A
3794    ftosizs s1, s0                              @ s1<- op
3795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3796    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3797    fsts    s1, [r9]                    @ vA<- s1
3798    GOTO_OPCODE(ip)                     @ jump to next instruction
3799
3800
3801/* ------------------------------ */
3802    .balign 64
3803.L_OP_FLOAT_TO_LONG: /* 0x88 */
3804/* File: armv6t2/OP_FLOAT_TO_LONG.S */
3805@include "armv6t2/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3806/* File: armv6t2/unopWider.S */
3807    /*
3808     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3809     * that specifies an instruction that performs "result = op r0", where
3810     * "result" is a 64-bit quantity in r0/r1.
3811     *
3812     * For: int-to-long, int-to-double, float-to-long, float-to-double
3813     */
3814    /* unop vA, vB */
3815    mov     r3, rINST, lsr #12          @ r3<- B
3816    ubfx    r9, rINST, #8, #4           @ r9<- A
3817    GET_VREG(r0, r3)                    @ r0<- vB
3818    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3819                               @ optional op; may set condition codes
3820    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3821    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3822    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3823    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3824    GOTO_OPCODE(ip)                     @ jump to next instruction
3825    /* 9-10 instructions */
3826
3827
3828
3829/* ------------------------------ */
3830    .balign 64
3831.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3832/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3833/* File: arm-vfp/funopWider.S */
3834    /*
3835     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3836     * "instr" line that specifies an instruction that performs "d0 = op s0".
3837     *
3838     * For: int-to-double, float-to-double
3839     */
3840    /* unop vA, vB */
3841    mov     r3, rINST, lsr #12          @ r3<- B
3842    mov     r9, rINST, lsr #8           @ r9<- A+
3843    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3844    flds    s0, [r3]                    @ s0<- vB
3845    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3846    and     r9, r9, #15                 @ r9<- A
3847    fcvtds  d0, s0                              @ d0<- op
3848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3849    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3850    fstd    d0, [r9]                    @ vA<- d0
3851    GOTO_OPCODE(ip)                     @ jump to next instruction
3852
3853
3854/* ------------------------------ */
3855    .balign 64
3856.L_OP_DOUBLE_TO_INT: /* 0x8a */
3857/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3858/* File: arm-vfp/funopNarrower.S */
3859    /*
3860     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3861     * "instr" line that specifies an instruction that performs "s0 = op d0".
3862     *
3863     * For: double-to-int, double-to-float
3864     */
3865    /* unop vA, vB */
3866    mov     r3, rINST, lsr #12          @ r3<- B
3867    mov     r9, rINST, lsr #8           @ r9<- A+
3868    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3869    fldd    d0, [r3]                    @ d0<- vB
3870    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3871    and     r9, r9, #15                 @ r9<- A
3872    ftosizd  s0, d0                              @ s0<- op
3873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3874    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3875    fsts    s0, [r9]                    @ vA<- s0
3876    GOTO_OPCODE(ip)                     @ jump to next instruction
3877
3878
3879/* ------------------------------ */
3880    .balign 64
3881.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3882/* File: armv6t2/OP_DOUBLE_TO_LONG.S */
3883@include "armv6t2/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3884/* File: armv6t2/unopWide.S */
3885    /*
3886     * Generic 64-bit unary operation.  Provide an "instr" line that
3887     * specifies an instruction that performs "result = op r0/r1".
3888     * This could be an ARM instruction or a function call.
3889     *
3890     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3891     */
3892    /* unop vA, vB */
3893    mov     r3, rINST, lsr #12          @ r3<- B
3894    ubfx    r9, rINST, #8, #4           @ r9<- A
3895    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3896    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3897    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3898    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3899                               @ optional op; may set condition codes
3900    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3901    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3902    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3903    GOTO_OPCODE(ip)                     @ jump to next instruction
3904    /* 10-11 instructions */
3905
3906
3907
3908/* ------------------------------ */
3909    .balign 64
3910.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3911/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3912/* File: arm-vfp/funopNarrower.S */
3913    /*
3914     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3915     * "instr" line that specifies an instruction that performs "s0 = op d0".
3916     *
3917     * For: double-to-int, double-to-float
3918     */
3919    /* unop vA, vB */
3920    mov     r3, rINST, lsr #12          @ r3<- B
3921    mov     r9, rINST, lsr #8           @ r9<- A+
3922    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3923    fldd    d0, [r3]                    @ d0<- vB
3924    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3925    and     r9, r9, #15                 @ r9<- A
3926    fcvtsd  s0, d0                              @ s0<- op
3927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3928    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3929    fsts    s0, [r9]                    @ vA<- s0
3930    GOTO_OPCODE(ip)                     @ jump to next instruction
3931
3932
3933/* ------------------------------ */
3934    .balign 64
3935.L_OP_INT_TO_BYTE: /* 0x8d */
3936/* File: armv6t2/OP_INT_TO_BYTE.S */
3937/* File: armv6t2/unop.S */
3938    /*
3939     * Generic 32-bit unary operation.  Provide an "instr" line that
3940     * specifies an instruction that performs "result = op r0".
3941     * This could be an ARM instruction or a function call.
3942     *
3943     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3944     *      int-to-byte, int-to-char, int-to-short
3945     */
3946    /* unop vA, vB */
3947    mov     r3, rINST, lsr #12          @ r3<- B
3948    ubfx    r9, rINST, #8, #4           @ r9<- A
3949    GET_VREG(r0, r3)                    @ r0<- vB
3950                               @ optional op; may set condition codes
3951    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3952    sxtb    r0, r0                              @ r0<- op, r0-r3 changed
3953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3954    SET_VREG(r0, r9)                    @ vAA<- r0
3955    GOTO_OPCODE(ip)                     @ jump to next instruction
3956    /* 8-9 instructions */
3957
3958
3959/* ------------------------------ */
3960    .balign 64
3961.L_OP_INT_TO_CHAR: /* 0x8e */
3962/* File: armv6t2/OP_INT_TO_CHAR.S */
3963/* File: armv6t2/unop.S */
3964    /*
3965     * Generic 32-bit unary operation.  Provide an "instr" line that
3966     * specifies an instruction that performs "result = op r0".
3967     * This could be an ARM instruction or a function call.
3968     *
3969     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3970     *      int-to-byte, int-to-char, int-to-short
3971     */
3972    /* unop vA, vB */
3973    mov     r3, rINST, lsr #12          @ r3<- B
3974    ubfx    r9, rINST, #8, #4           @ r9<- A
3975    GET_VREG(r0, r3)                    @ r0<- vB
3976                               @ optional op; may set condition codes
3977    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3978    uxth    r0, r0                              @ r0<- op, r0-r3 changed
3979    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3980    SET_VREG(r0, r9)                    @ vAA<- r0
3981    GOTO_OPCODE(ip)                     @ jump to next instruction
3982    /* 8-9 instructions */
3983
3984
3985/* ------------------------------ */
3986    .balign 64
3987.L_OP_INT_TO_SHORT: /* 0x8f */
3988/* File: armv6t2/OP_INT_TO_SHORT.S */
3989/* File: armv6t2/unop.S */
3990    /*
3991     * Generic 32-bit unary operation.  Provide an "instr" line that
3992     * specifies an instruction that performs "result = op r0".
3993     * This could be an ARM instruction or a function call.
3994     *
3995     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3996     *      int-to-byte, int-to-char, int-to-short
3997     */
3998    /* unop vA, vB */
3999    mov     r3, rINST, lsr #12          @ r3<- B
4000    ubfx    r9, rINST, #8, #4           @ r9<- A
4001    GET_VREG(r0, r3)                    @ r0<- vB
4002                               @ optional op; may set condition codes
4003    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4004    sxth    r0, r0                              @ r0<- op, r0-r3 changed
4005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4006    SET_VREG(r0, r9)                    @ vAA<- r0
4007    GOTO_OPCODE(ip)                     @ jump to next instruction
4008    /* 8-9 instructions */
4009
4010
4011/* ------------------------------ */
4012    .balign 64
4013.L_OP_ADD_INT: /* 0x90 */
4014/* File: armv5te/OP_ADD_INT.S */
4015/* File: armv5te/binop.S */
4016    /*
4017     * Generic 32-bit binary operation.  Provide an "instr" line that
4018     * specifies an instruction that performs "result = r0 op r1".
4019     * This could be an ARM instruction or a function call.  (If the result
4020     * comes back in a register other than r0, you can override "result".)
4021     *
4022     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4023     * vCC (r1).  Useful for integer division and modulus.  Note that we
4024     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4025     * handles it correctly.
4026     *
4027     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4028     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4029     *      mul-float, div-float, rem-float
4030     */
4031    /* binop vAA, vBB, vCC */
4032    FETCH(r0, 1)                        @ r0<- CCBB
4033    mov     r9, rINST, lsr #8           @ r9<- AA
4034    mov     r3, r0, lsr #8              @ r3<- CC
4035    and     r2, r0, #255                @ r2<- BB
4036    GET_VREG(r1, r3)                    @ r1<- vCC
4037    GET_VREG(r0, r2)                    @ r0<- vBB
4038    .if 0
4039    cmp     r1, #0                      @ is second operand zero?
4040    beq     common_errDivideByZero
4041    .endif
4042
4043    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4044                               @ optional op; may set condition codes
4045    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4046    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4047    SET_VREG(r0, r9)               @ vAA<- r0
4048    GOTO_OPCODE(ip)                     @ jump to next instruction
4049    /* 11-14 instructions */
4050
4051
4052/* ------------------------------ */
4053    .balign 64
4054.L_OP_SUB_INT: /* 0x91 */
4055/* File: armv5te/OP_SUB_INT.S */
4056/* File: armv5te/binop.S */
4057    /*
4058     * Generic 32-bit binary operation.  Provide an "instr" line that
4059     * specifies an instruction that performs "result = r0 op r1".
4060     * This could be an ARM instruction or a function call.  (If the result
4061     * comes back in a register other than r0, you can override "result".)
4062     *
4063     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4064     * vCC (r1).  Useful for integer division and modulus.  Note that we
4065     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4066     * handles it correctly.
4067     *
4068     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4069     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4070     *      mul-float, div-float, rem-float
4071     */
4072    /* binop vAA, vBB, vCC */
4073    FETCH(r0, 1)                        @ r0<- CCBB
4074    mov     r9, rINST, lsr #8           @ r9<- AA
4075    mov     r3, r0, lsr #8              @ r3<- CC
4076    and     r2, r0, #255                @ r2<- BB
4077    GET_VREG(r1, r3)                    @ r1<- vCC
4078    GET_VREG(r0, r2)                    @ r0<- vBB
4079    .if 0
4080    cmp     r1, #0                      @ is second operand zero?
4081    beq     common_errDivideByZero
4082    .endif
4083
4084    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4085                               @ optional op; may set condition codes
4086    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4088    SET_VREG(r0, r9)               @ vAA<- r0
4089    GOTO_OPCODE(ip)                     @ jump to next instruction
4090    /* 11-14 instructions */
4091
4092
4093/* ------------------------------ */
4094    .balign 64
4095.L_OP_MUL_INT: /* 0x92 */
4096/* File: armv5te/OP_MUL_INT.S */
4097/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4098/* File: armv5te/binop.S */
4099    /*
4100     * Generic 32-bit binary operation.  Provide an "instr" line that
4101     * specifies an instruction that performs "result = r0 op r1".
4102     * This could be an ARM instruction or a function call.  (If the result
4103     * comes back in a register other than r0, you can override "result".)
4104     *
4105     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4106     * vCC (r1).  Useful for integer division and modulus.  Note that we
4107     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4108     * handles it correctly.
4109     *
4110     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4111     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4112     *      mul-float, div-float, rem-float
4113     */
4114    /* binop vAA, vBB, vCC */
4115    FETCH(r0, 1)                        @ r0<- CCBB
4116    mov     r9, rINST, lsr #8           @ r9<- AA
4117    mov     r3, r0, lsr #8              @ r3<- CC
4118    and     r2, r0, #255                @ r2<- BB
4119    GET_VREG(r1, r3)                    @ r1<- vCC
4120    GET_VREG(r0, r2)                    @ r0<- vBB
4121    .if 0
4122    cmp     r1, #0                      @ is second operand zero?
4123    beq     common_errDivideByZero
4124    .endif
4125
4126    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4127                               @ optional op; may set condition codes
4128    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4129    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4130    SET_VREG(r0, r9)               @ vAA<- r0
4131    GOTO_OPCODE(ip)                     @ jump to next instruction
4132    /* 11-14 instructions */
4133
4134
4135/* ------------------------------ */
4136    .balign 64
4137.L_OP_DIV_INT: /* 0x93 */
4138/* File: armv5te/OP_DIV_INT.S */
4139/* File: armv5te/binop.S */
4140    /*
4141     * Generic 32-bit binary operation.  Provide an "instr" line that
4142     * specifies an instruction that performs "result = r0 op r1".
4143     * This could be an ARM instruction or a function call.  (If the result
4144     * comes back in a register other than r0, you can override "result".)
4145     *
4146     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4147     * vCC (r1).  Useful for integer division and modulus.  Note that we
4148     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4149     * handles it correctly.
4150     *
4151     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4152     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4153     *      mul-float, div-float, rem-float
4154     */
4155    /* binop vAA, vBB, vCC */
4156    FETCH(r0, 1)                        @ r0<- CCBB
4157    mov     r9, rINST, lsr #8           @ r9<- AA
4158    mov     r3, r0, lsr #8              @ r3<- CC
4159    and     r2, r0, #255                @ r2<- BB
4160    GET_VREG(r1, r3)                    @ r1<- vCC
4161    GET_VREG(r0, r2)                    @ r0<- vBB
4162    .if 1
4163    cmp     r1, #0                      @ is second operand zero?
4164    beq     common_errDivideByZero
4165    .endif
4166
4167    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4168                               @ optional op; may set condition codes
4169    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4171    SET_VREG(r0, r9)               @ vAA<- r0
4172    GOTO_OPCODE(ip)                     @ jump to next instruction
4173    /* 11-14 instructions */
4174
4175
4176/* ------------------------------ */
4177    .balign 64
4178.L_OP_REM_INT: /* 0x94 */
4179/* File: armv5te/OP_REM_INT.S */
4180/* idivmod returns quotient in r0 and remainder in r1 */
4181/* File: armv5te/binop.S */
4182    /*
4183     * Generic 32-bit binary operation.  Provide an "instr" line that
4184     * specifies an instruction that performs "result = r0 op r1".
4185     * This could be an ARM instruction or a function call.  (If the result
4186     * comes back in a register other than r0, you can override "result".)
4187     *
4188     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4189     * vCC (r1).  Useful for integer division and modulus.  Note that we
4190     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4191     * handles it correctly.
4192     *
4193     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4194     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4195     *      mul-float, div-float, rem-float
4196     */
4197    /* binop vAA, vBB, vCC */
4198    FETCH(r0, 1)                        @ r0<- CCBB
4199    mov     r9, rINST, lsr #8           @ r9<- AA
4200    mov     r3, r0, lsr #8              @ r3<- CC
4201    and     r2, r0, #255                @ r2<- BB
4202    GET_VREG(r1, r3)                    @ r1<- vCC
4203    GET_VREG(r0, r2)                    @ r0<- vBB
4204    .if 1
4205    cmp     r1, #0                      @ is second operand zero?
4206    beq     common_errDivideByZero
4207    .endif
4208
4209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4210                               @ optional op; may set condition codes
4211    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4213    SET_VREG(r1, r9)               @ vAA<- r1
4214    GOTO_OPCODE(ip)                     @ jump to next instruction
4215    /* 11-14 instructions */
4216
4217
4218/* ------------------------------ */
4219    .balign 64
4220.L_OP_AND_INT: /* 0x95 */
4221/* File: armv5te/OP_AND_INT.S */
4222/* File: armv5te/binop.S */
4223    /*
4224     * Generic 32-bit binary operation.  Provide an "instr" line that
4225     * specifies an instruction that performs "result = r0 op r1".
4226     * This could be an ARM instruction or a function call.  (If the result
4227     * comes back in a register other than r0, you can override "result".)
4228     *
4229     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4230     * vCC (r1).  Useful for integer division and modulus.  Note that we
4231     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4232     * handles it correctly.
4233     *
4234     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4235     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4236     *      mul-float, div-float, rem-float
4237     */
4238    /* binop vAA, vBB, vCC */
4239    FETCH(r0, 1)                        @ r0<- CCBB
4240    mov     r9, rINST, lsr #8           @ r9<- AA
4241    mov     r3, r0, lsr #8              @ r3<- CC
4242    and     r2, r0, #255                @ r2<- BB
4243    GET_VREG(r1, r3)                    @ r1<- vCC
4244    GET_VREG(r0, r2)                    @ r0<- vBB
4245    .if 0
4246    cmp     r1, #0                      @ is second operand zero?
4247    beq     common_errDivideByZero
4248    .endif
4249
4250    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4251                               @ optional op; may set condition codes
4252    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4254    SET_VREG(r0, r9)               @ vAA<- r0
4255    GOTO_OPCODE(ip)                     @ jump to next instruction
4256    /* 11-14 instructions */
4257
4258
4259/* ------------------------------ */
4260    .balign 64
4261.L_OP_OR_INT: /* 0x96 */
4262/* File: armv5te/OP_OR_INT.S */
4263/* File: armv5te/binop.S */
4264    /*
4265     * Generic 32-bit binary operation.  Provide an "instr" line that
4266     * specifies an instruction that performs "result = r0 op r1".
4267     * This could be an ARM instruction or a function call.  (If the result
4268     * comes back in a register other than r0, you can override "result".)
4269     *
4270     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4271     * vCC (r1).  Useful for integer division and modulus.  Note that we
4272     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4273     * handles it correctly.
4274     *
4275     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4276     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4277     *      mul-float, div-float, rem-float
4278     */
4279    /* binop vAA, vBB, vCC */
4280    FETCH(r0, 1)                        @ r0<- CCBB
4281    mov     r9, rINST, lsr #8           @ r9<- AA
4282    mov     r3, r0, lsr #8              @ r3<- CC
4283    and     r2, r0, #255                @ r2<- BB
4284    GET_VREG(r1, r3)                    @ r1<- vCC
4285    GET_VREG(r0, r2)                    @ r0<- vBB
4286    .if 0
4287    cmp     r1, #0                      @ is second operand zero?
4288    beq     common_errDivideByZero
4289    .endif
4290
4291    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4292                               @ optional op; may set condition codes
4293    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4295    SET_VREG(r0, r9)               @ vAA<- r0
4296    GOTO_OPCODE(ip)                     @ jump to next instruction
4297    /* 11-14 instructions */
4298
4299
4300/* ------------------------------ */
4301    .balign 64
4302.L_OP_XOR_INT: /* 0x97 */
4303/* File: armv5te/OP_XOR_INT.S */
4304/* File: armv5te/binop.S */
4305    /*
4306     * Generic 32-bit binary operation.  Provide an "instr" line that
4307     * specifies an instruction that performs "result = r0 op r1".
4308     * This could be an ARM instruction or a function call.  (If the result
4309     * comes back in a register other than r0, you can override "result".)
4310     *
4311     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4312     * vCC (r1).  Useful for integer division and modulus.  Note that we
4313     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4314     * handles it correctly.
4315     *
4316     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4317     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4318     *      mul-float, div-float, rem-float
4319     */
4320    /* binop vAA, vBB, vCC */
4321    FETCH(r0, 1)                        @ r0<- CCBB
4322    mov     r9, rINST, lsr #8           @ r9<- AA
4323    mov     r3, r0, lsr #8              @ r3<- CC
4324    and     r2, r0, #255                @ r2<- BB
4325    GET_VREG(r1, r3)                    @ r1<- vCC
4326    GET_VREG(r0, r2)                    @ r0<- vBB
4327    .if 0
4328    cmp     r1, #0                      @ is second operand zero?
4329    beq     common_errDivideByZero
4330    .endif
4331
4332    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4333                               @ optional op; may set condition codes
4334    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4336    SET_VREG(r0, r9)               @ vAA<- r0
4337    GOTO_OPCODE(ip)                     @ jump to next instruction
4338    /* 11-14 instructions */
4339
4340
4341/* ------------------------------ */
4342    .balign 64
4343.L_OP_SHL_INT: /* 0x98 */
4344/* File: armv5te/OP_SHL_INT.S */
4345/* File: armv5te/binop.S */
4346    /*
4347     * Generic 32-bit binary operation.  Provide an "instr" line that
4348     * specifies an instruction that performs "result = r0 op r1".
4349     * This could be an ARM instruction or a function call.  (If the result
4350     * comes back in a register other than r0, you can override "result".)
4351     *
4352     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4353     * vCC (r1).  Useful for integer division and modulus.  Note that we
4354     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4355     * handles it correctly.
4356     *
4357     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4358     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4359     *      mul-float, div-float, rem-float
4360     */
4361    /* binop vAA, vBB, vCC */
4362    FETCH(r0, 1)                        @ r0<- CCBB
4363    mov     r9, rINST, lsr #8           @ r9<- AA
4364    mov     r3, r0, lsr #8              @ r3<- CC
4365    and     r2, r0, #255                @ r2<- BB
4366    GET_VREG(r1, r3)                    @ r1<- vCC
4367    GET_VREG(r0, r2)                    @ r0<- vBB
4368    .if 0
4369    cmp     r1, #0                      @ is second operand zero?
4370    beq     common_errDivideByZero
4371    .endif
4372
4373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4374    and     r1, r1, #31                           @ optional op; may set condition codes
4375    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4376    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4377    SET_VREG(r0, r9)               @ vAA<- r0
4378    GOTO_OPCODE(ip)                     @ jump to next instruction
4379    /* 11-14 instructions */
4380
4381
4382/* ------------------------------ */
4383    .balign 64
4384.L_OP_SHR_INT: /* 0x99 */
4385/* File: armv5te/OP_SHR_INT.S */
4386/* File: armv5te/binop.S */
4387    /*
4388     * Generic 32-bit binary operation.  Provide an "instr" line that
4389     * specifies an instruction that performs "result = r0 op r1".
4390     * This could be an ARM instruction or a function call.  (If the result
4391     * comes back in a register other than r0, you can override "result".)
4392     *
4393     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4394     * vCC (r1).  Useful for integer division and modulus.  Note that we
4395     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4396     * handles it correctly.
4397     *
4398     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4399     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4400     *      mul-float, div-float, rem-float
4401     */
4402    /* binop vAA, vBB, vCC */
4403    FETCH(r0, 1)                        @ r0<- CCBB
4404    mov     r9, rINST, lsr #8           @ r9<- AA
4405    mov     r3, r0, lsr #8              @ r3<- CC
4406    and     r2, r0, #255                @ r2<- BB
4407    GET_VREG(r1, r3)                    @ r1<- vCC
4408    GET_VREG(r0, r2)                    @ r0<- vBB
4409    .if 0
4410    cmp     r1, #0                      @ is second operand zero?
4411    beq     common_errDivideByZero
4412    .endif
4413
4414    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4415    and     r1, r1, #31                           @ optional op; may set condition codes
4416    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4417    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4418    SET_VREG(r0, r9)               @ vAA<- r0
4419    GOTO_OPCODE(ip)                     @ jump to next instruction
4420    /* 11-14 instructions */
4421
4422
4423/* ------------------------------ */
4424    .balign 64
4425.L_OP_USHR_INT: /* 0x9a */
4426/* File: armv5te/OP_USHR_INT.S */
4427/* File: armv5te/binop.S */
4428    /*
4429     * Generic 32-bit binary operation.  Provide an "instr" line that
4430     * specifies an instruction that performs "result = r0 op r1".
4431     * This could be an ARM instruction or a function call.  (If the result
4432     * comes back in a register other than r0, you can override "result".)
4433     *
4434     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4435     * vCC (r1).  Useful for integer division and modulus.  Note that we
4436     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4437     * handles it correctly.
4438     *
4439     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4440     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4441     *      mul-float, div-float, rem-float
4442     */
4443    /* binop vAA, vBB, vCC */
4444    FETCH(r0, 1)                        @ r0<- CCBB
4445    mov     r9, rINST, lsr #8           @ r9<- AA
4446    mov     r3, r0, lsr #8              @ r3<- CC
4447    and     r2, r0, #255                @ r2<- BB
4448    GET_VREG(r1, r3)                    @ r1<- vCC
4449    GET_VREG(r0, r2)                    @ r0<- vBB
4450    .if 0
4451    cmp     r1, #0                      @ is second operand zero?
4452    beq     common_errDivideByZero
4453    .endif
4454
4455    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4456    and     r1, r1, #31                           @ optional op; may set condition codes
4457    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4458    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4459    SET_VREG(r0, r9)               @ vAA<- r0
4460    GOTO_OPCODE(ip)                     @ jump to next instruction
4461    /* 11-14 instructions */
4462
4463
4464/* ------------------------------ */
4465    .balign 64
4466.L_OP_ADD_LONG: /* 0x9b */
4467/* File: armv5te/OP_ADD_LONG.S */
4468/* File: armv5te/binopWide.S */
4469    /*
4470     * Generic 64-bit binary operation.  Provide an "instr" line that
4471     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4472     * This could be an ARM instruction or a function call.  (If the result
4473     * comes back in a register other than r0, you can override "result".)
4474     *
4475     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4476     * vCC (r1).  Useful for integer division and modulus.
4477     *
4478     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4479     *      xor-long, add-double, sub-double, mul-double, div-double,
4480     *      rem-double
4481     *
4482     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4483     */
4484    /* binop vAA, vBB, vCC */
4485    FETCH(r0, 1)                        @ r0<- CCBB
4486    mov     r9, rINST, lsr #8           @ r9<- AA
4487    and     r2, r0, #255                @ r2<- BB
4488    mov     r3, r0, lsr #8              @ r3<- CC
4489    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4490    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4491    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4492    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4493    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4494    .if 0
4495    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4496    beq     common_errDivideByZero
4497    .endif
4498    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4499
4500    adds    r0, r0, r2                           @ optional op; may set condition codes
4501    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4502    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4503    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4504    GOTO_OPCODE(ip)                     @ jump to next instruction
4505    /* 14-17 instructions */
4506
4507
4508/* ------------------------------ */
4509    .balign 64
4510.L_OP_SUB_LONG: /* 0x9c */
4511/* File: armv5te/OP_SUB_LONG.S */
4512/* File: armv5te/binopWide.S */
4513    /*
4514     * Generic 64-bit binary operation.  Provide an "instr" line that
4515     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4516     * This could be an ARM instruction or a function call.  (If the result
4517     * comes back in a register other than r0, you can override "result".)
4518     *
4519     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4520     * vCC (r1).  Useful for integer division and modulus.
4521     *
4522     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4523     *      xor-long, add-double, sub-double, mul-double, div-double,
4524     *      rem-double
4525     *
4526     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4527     */
4528    /* binop vAA, vBB, vCC */
4529    FETCH(r0, 1)                        @ r0<- CCBB
4530    mov     r9, rINST, lsr #8           @ r9<- AA
4531    and     r2, r0, #255                @ r2<- BB
4532    mov     r3, r0, lsr #8              @ r3<- CC
4533    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4534    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4535    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4536    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4537    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4538    .if 0
4539    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4540    beq     common_errDivideByZero
4541    .endif
4542    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4543
4544    subs    r0, r0, r2                           @ optional op; may set condition codes
4545    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4547    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4548    GOTO_OPCODE(ip)                     @ jump to next instruction
4549    /* 14-17 instructions */
4550
4551
4552/* ------------------------------ */
4553    .balign 64
4554.L_OP_MUL_LONG: /* 0x9d */
4555/* File: armv5te/OP_MUL_LONG.S */
4556    /*
4557     * Signed 64-bit integer multiply.
4558     *
4559     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4560     *        WX
4561     *      x YZ
4562     *  --------
4563     *     ZW ZX
4564     *  YW YX
4565     *
4566     * The low word of the result holds ZX, the high word holds
4567     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4568     * it doesn't fit in the low 64 bits.
4569     *
4570     * Unlike most ARM math operations, multiply instructions have
4571     * restrictions on using the same register more than once (Rd and Rm
4572     * cannot be the same).
4573     */
4574    /* mul-long vAA, vBB, vCC */
4575    FETCH(r0, 1)                        @ r0<- CCBB
4576    and     r2, r0, #255                @ r2<- BB
4577    mov     r3, r0, lsr #8              @ r3<- CC
4578    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4579    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4580    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4581    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4582    mul     ip, r2, r1                  @  ip<- ZxW
4583    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4584    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4585    mov     r0, rINST, lsr #8           @ r0<- AA
4586    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4587    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4588    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4589    b       .LOP_MUL_LONG_finish
4590
4591/* ------------------------------ */
4592    .balign 64
4593.L_OP_DIV_LONG: /* 0x9e */
4594/* File: armv5te/OP_DIV_LONG.S */
4595/* File: armv5te/binopWide.S */
4596    /*
4597     * Generic 64-bit binary operation.  Provide an "instr" line that
4598     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4599     * This could be an ARM instruction or a function call.  (If the result
4600     * comes back in a register other than r0, you can override "result".)
4601     *
4602     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4603     * vCC (r1).  Useful for integer division and modulus.
4604     *
4605     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4606     *      xor-long, add-double, sub-double, mul-double, div-double,
4607     *      rem-double
4608     *
4609     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4610     */
4611    /* binop vAA, vBB, vCC */
4612    FETCH(r0, 1)                        @ r0<- CCBB
4613    mov     r9, rINST, lsr #8           @ r9<- AA
4614    and     r2, r0, #255                @ r2<- BB
4615    mov     r3, r0, lsr #8              @ r3<- CC
4616    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4617    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4618    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4619    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4620    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4621    .if 1
4622    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4623    beq     common_errDivideByZero
4624    .endif
4625    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4626
4627                               @ optional op; may set condition codes
4628    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4629    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4630    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4631    GOTO_OPCODE(ip)                     @ jump to next instruction
4632    /* 14-17 instructions */
4633
4634
4635/* ------------------------------ */
4636    .balign 64
4637.L_OP_REM_LONG: /* 0x9f */
4638/* File: armv5te/OP_REM_LONG.S */
4639/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4640/* File: armv5te/binopWide.S */
4641    /*
4642     * Generic 64-bit binary operation.  Provide an "instr" line that
4643     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4644     * This could be an ARM instruction or a function call.  (If the result
4645     * comes back in a register other than r0, you can override "result".)
4646     *
4647     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4648     * vCC (r1).  Useful for integer division and modulus.
4649     *
4650     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4651     *      xor-long, add-double, sub-double, mul-double, div-double,
4652     *      rem-double
4653     *
4654     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4655     */
4656    /* binop vAA, vBB, vCC */
4657    FETCH(r0, 1)                        @ r0<- CCBB
4658    mov     r9, rINST, lsr #8           @ r9<- AA
4659    and     r2, r0, #255                @ r2<- BB
4660    mov     r3, r0, lsr #8              @ r3<- CC
4661    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4662    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4663    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4664    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4665    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4666    .if 1
4667    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4668    beq     common_errDivideByZero
4669    .endif
4670    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4671
4672                               @ optional op; may set condition codes
4673    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4674    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4675    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4676    GOTO_OPCODE(ip)                     @ jump to next instruction
4677    /* 14-17 instructions */
4678
4679
4680/* ------------------------------ */
4681    .balign 64
4682.L_OP_AND_LONG: /* 0xa0 */
4683/* File: armv5te/OP_AND_LONG.S */
4684/* File: armv5te/binopWide.S */
4685    /*
4686     * Generic 64-bit binary operation.  Provide an "instr" line that
4687     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4688     * This could be an ARM instruction or a function call.  (If the result
4689     * comes back in a register other than r0, you can override "result".)
4690     *
4691     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4692     * vCC (r1).  Useful for integer division and modulus.
4693     *
4694     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4695     *      xor-long, add-double, sub-double, mul-double, div-double,
4696     *      rem-double
4697     *
4698     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4699     */
4700    /* binop vAA, vBB, vCC */
4701    FETCH(r0, 1)                        @ r0<- CCBB
4702    mov     r9, rINST, lsr #8           @ r9<- AA
4703    and     r2, r0, #255                @ r2<- BB
4704    mov     r3, r0, lsr #8              @ r3<- CC
4705    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4706    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4707    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4708    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4709    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4710    .if 0
4711    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4712    beq     common_errDivideByZero
4713    .endif
4714    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4715
4716    and     r0, r0, r2                           @ optional op; may set condition codes
4717    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4719    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4720    GOTO_OPCODE(ip)                     @ jump to next instruction
4721    /* 14-17 instructions */
4722
4723
4724/* ------------------------------ */
4725    .balign 64
4726.L_OP_OR_LONG: /* 0xa1 */
4727/* File: armv5te/OP_OR_LONG.S */
4728/* File: armv5te/binopWide.S */
4729    /*
4730     * Generic 64-bit binary operation.  Provide an "instr" line that
4731     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4732     * This could be an ARM instruction or a function call.  (If the result
4733     * comes back in a register other than r0, you can override "result".)
4734     *
4735     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4736     * vCC (r1).  Useful for integer division and modulus.
4737     *
4738     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4739     *      xor-long, add-double, sub-double, mul-double, div-double,
4740     *      rem-double
4741     *
4742     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4743     */
4744    /* binop vAA, vBB, vCC */
4745    FETCH(r0, 1)                        @ r0<- CCBB
4746    mov     r9, rINST, lsr #8           @ r9<- AA
4747    and     r2, r0, #255                @ r2<- BB
4748    mov     r3, r0, lsr #8              @ r3<- CC
4749    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4750    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4751    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4752    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4753    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4754    .if 0
4755    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4756    beq     common_errDivideByZero
4757    .endif
4758    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4759
4760    orr     r0, r0, r2                           @ optional op; may set condition codes
4761    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4763    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4764    GOTO_OPCODE(ip)                     @ jump to next instruction
4765    /* 14-17 instructions */
4766
4767
4768/* ------------------------------ */
4769    .balign 64
4770.L_OP_XOR_LONG: /* 0xa2 */
4771/* File: armv5te/OP_XOR_LONG.S */
4772/* File: armv5te/binopWide.S */
4773    /*
4774     * Generic 64-bit binary operation.  Provide an "instr" line that
4775     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4776     * This could be an ARM instruction or a function call.  (If the result
4777     * comes back in a register other than r0, you can override "result".)
4778     *
4779     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4780     * vCC (r1).  Useful for integer division and modulus.
4781     *
4782     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4783     *      xor-long, add-double, sub-double, mul-double, div-double,
4784     *      rem-double
4785     *
4786     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4787     */
4788    /* binop vAA, vBB, vCC */
4789    FETCH(r0, 1)                        @ r0<- CCBB
4790    mov     r9, rINST, lsr #8           @ r9<- AA
4791    and     r2, r0, #255                @ r2<- BB
4792    mov     r3, r0, lsr #8              @ r3<- CC
4793    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4794    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4795    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4796    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4797    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4798    .if 0
4799    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4800    beq     common_errDivideByZero
4801    .endif
4802    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4803
4804    eor     r0, r0, r2                           @ optional op; may set condition codes
4805    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4806    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4807    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4808    GOTO_OPCODE(ip)                     @ jump to next instruction
4809    /* 14-17 instructions */
4810
4811
4812/* ------------------------------ */
4813    .balign 64
4814.L_OP_SHL_LONG: /* 0xa3 */
4815/* File: armv5te/OP_SHL_LONG.S */
4816    /*
4817     * Long integer shift.  This is different from the generic 32/64-bit
4818     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4819     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4820     * 6 bits of the shift distance.
4821     */
4822    /* shl-long vAA, vBB, vCC */
4823    FETCH(r0, 1)                        @ r0<- CCBB
4824    mov     r9, rINST, lsr #8           @ r9<- AA
4825    and     r3, r0, #255                @ r3<- BB
4826    mov     r0, r0, lsr #8              @ r0<- CC
4827    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4828    GET_VREG(r2, r0)                    @ r2<- vCC
4829    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4830    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4831    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4832
4833    mov     r1, r1, asl r2              @  r1<- r1 << r2
4834    rsb     r3, r2, #32                 @  r3<- 32 - r2
4835    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4836    subs    ip, r2, #32                 @  ip<- r2 - 32
4837    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4839    b       .LOP_SHL_LONG_finish
4840
4841/* ------------------------------ */
4842    .balign 64
4843.L_OP_SHR_LONG: /* 0xa4 */
4844/* File: armv5te/OP_SHR_LONG.S */
4845    /*
4846     * Long integer shift.  This is different from the generic 32/64-bit
4847     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4848     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4849     * 6 bits of the shift distance.
4850     */
4851    /* shr-long vAA, vBB, vCC */
4852    FETCH(r0, 1)                        @ r0<- CCBB
4853    mov     r9, rINST, lsr #8           @ r9<- AA
4854    and     r3, r0, #255                @ r3<- BB
4855    mov     r0, r0, lsr #8              @ r0<- CC
4856    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4857    GET_VREG(r2, r0)                    @ r2<- vCC
4858    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4859    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4860    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4861
4862    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4863    rsb     r3, r2, #32                 @  r3<- 32 - r2
4864    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4865    subs    ip, r2, #32                 @  ip<- r2 - 32
4866    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4867    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4868    b       .LOP_SHR_LONG_finish
4869
4870/* ------------------------------ */
4871    .balign 64
4872.L_OP_USHR_LONG: /* 0xa5 */
4873/* File: armv5te/OP_USHR_LONG.S */
4874    /*
4875     * Long integer shift.  This is different from the generic 32/64-bit
4876     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4877     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4878     * 6 bits of the shift distance.
4879     */
4880    /* ushr-long vAA, vBB, vCC */
4881    FETCH(r0, 1)                        @ r0<- CCBB
4882    mov     r9, rINST, lsr #8           @ r9<- AA
4883    and     r3, r0, #255                @ r3<- BB
4884    mov     r0, r0, lsr #8              @ r0<- CC
4885    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4886    GET_VREG(r2, r0)                    @ r2<- vCC
4887    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4888    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4889    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4890
4891    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4892    rsb     r3, r2, #32                 @  r3<- 32 - r2
4893    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4894    subs    ip, r2, #32                 @  ip<- r2 - 32
4895    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4897    b       .LOP_USHR_LONG_finish
4898
4899/* ------------------------------ */
4900    .balign 64
4901.L_OP_ADD_FLOAT: /* 0xa6 */
4902/* File: arm-vfp/OP_ADD_FLOAT.S */
4903/* File: arm-vfp/fbinop.S */
4904    /*
4905     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4906     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4907     * use the "softfp" ABI, this must be an instruction, not a function call.
4908     *
4909     * For: add-float, sub-float, mul-float, div-float
4910     */
4911    /* floatop vAA, vBB, vCC */
4912    FETCH(r0, 1)                        @ r0<- CCBB
4913    mov     r9, rINST, lsr #8           @ r9<- AA
4914    mov     r3, r0, lsr #8              @ r3<- CC
4915    and     r2, r0, #255                @ r2<- BB
4916    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4917    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4918    flds    s1, [r3]                    @ s1<- vCC
4919    flds    s0, [r2]                    @ s0<- vBB
4920
4921    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4922    fadds   s2, s0, s1                              @ s2<- op
4923    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4924    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4925    fsts    s2, [r9]                    @ vAA<- s2
4926    GOTO_OPCODE(ip)                     @ jump to next instruction
4927
4928
4929/* ------------------------------ */
4930    .balign 64
4931.L_OP_SUB_FLOAT: /* 0xa7 */
4932/* File: arm-vfp/OP_SUB_FLOAT.S */
4933/* File: arm-vfp/fbinop.S */
4934    /*
4935     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4936     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4937     * use the "softfp" ABI, this must be an instruction, not a function call.
4938     *
4939     * For: add-float, sub-float, mul-float, div-float
4940     */
4941    /* floatop vAA, vBB, vCC */
4942    FETCH(r0, 1)                        @ r0<- CCBB
4943    mov     r9, rINST, lsr #8           @ r9<- AA
4944    mov     r3, r0, lsr #8              @ r3<- CC
4945    and     r2, r0, #255                @ r2<- BB
4946    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4947    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4948    flds    s1, [r3]                    @ s1<- vCC
4949    flds    s0, [r2]                    @ s0<- vBB
4950
4951    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4952    fsubs   s2, s0, s1                              @ s2<- op
4953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4954    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4955    fsts    s2, [r9]                    @ vAA<- s2
4956    GOTO_OPCODE(ip)                     @ jump to next instruction
4957
4958
4959/* ------------------------------ */
4960    .balign 64
4961.L_OP_MUL_FLOAT: /* 0xa8 */
4962/* File: arm-vfp/OP_MUL_FLOAT.S */
4963/* File: arm-vfp/fbinop.S */
4964    /*
4965     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4966     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4967     * use the "softfp" ABI, this must be an instruction, not a function call.
4968     *
4969     * For: add-float, sub-float, mul-float, div-float
4970     */
4971    /* floatop vAA, vBB, vCC */
4972    FETCH(r0, 1)                        @ r0<- CCBB
4973    mov     r9, rINST, lsr #8           @ r9<- AA
4974    mov     r3, r0, lsr #8              @ r3<- CC
4975    and     r2, r0, #255                @ r2<- BB
4976    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4977    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4978    flds    s1, [r3]                    @ s1<- vCC
4979    flds    s0, [r2]                    @ s0<- vBB
4980
4981    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4982    fmuls   s2, s0, s1                              @ s2<- op
4983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4984    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4985    fsts    s2, [r9]                    @ vAA<- s2
4986    GOTO_OPCODE(ip)                     @ jump to next instruction
4987
4988
4989/* ------------------------------ */
4990    .balign 64
4991.L_OP_DIV_FLOAT: /* 0xa9 */
4992/* File: arm-vfp/OP_DIV_FLOAT.S */
4993/* File: arm-vfp/fbinop.S */
4994    /*
4995     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4996     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4997     * use the "softfp" ABI, this must be an instruction, not a function call.
4998     *
4999     * For: add-float, sub-float, mul-float, div-float
5000     */
5001    /* floatop vAA, vBB, vCC */
5002    FETCH(r0, 1)                        @ r0<- CCBB
5003    mov     r9, rINST, lsr #8           @ r9<- AA
5004    mov     r3, r0, lsr #8              @ r3<- CC
5005    and     r2, r0, #255                @ r2<- BB
5006    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5007    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5008    flds    s1, [r3]                    @ s1<- vCC
5009    flds    s0, [r2]                    @ s0<- vBB
5010
5011    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5012    fdivs   s2, s0, s1                              @ s2<- op
5013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5014    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5015    fsts    s2, [r9]                    @ vAA<- s2
5016    GOTO_OPCODE(ip)                     @ jump to next instruction
5017
5018
5019/* ------------------------------ */
5020    .balign 64
5021.L_OP_REM_FLOAT: /* 0xaa */
5022/* File: armv5te/OP_REM_FLOAT.S */
5023/* EABI doesn't define a float remainder function, but libm does */
5024/* File: armv5te/binop.S */
5025    /*
5026     * Generic 32-bit binary operation.  Provide an "instr" line that
5027     * specifies an instruction that performs "result = r0 op r1".
5028     * This could be an ARM instruction or a function call.  (If the result
5029     * comes back in a register other than r0, you can override "result".)
5030     *
5031     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5032     * vCC (r1).  Useful for integer division and modulus.  Note that we
5033     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5034     * handles it correctly.
5035     *
5036     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5037     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5038     *      mul-float, div-float, rem-float
5039     */
5040    /* binop vAA, vBB, vCC */
5041    FETCH(r0, 1)                        @ r0<- CCBB
5042    mov     r9, rINST, lsr #8           @ r9<- AA
5043    mov     r3, r0, lsr #8              @ r3<- CC
5044    and     r2, r0, #255                @ r2<- BB
5045    GET_VREG(r1, r3)                    @ r1<- vCC
5046    GET_VREG(r0, r2)                    @ r0<- vBB
5047    .if 0
5048    cmp     r1, #0                      @ is second operand zero?
5049    beq     common_errDivideByZero
5050    .endif
5051
5052    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5053                               @ optional op; may set condition codes
5054    bl      fmodf                              @ r0<- op, r0-r3 changed
5055    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5056    SET_VREG(r0, r9)               @ vAA<- r0
5057    GOTO_OPCODE(ip)                     @ jump to next instruction
5058    /* 11-14 instructions */
5059
5060
5061/* ------------------------------ */
5062    .balign 64
5063.L_OP_ADD_DOUBLE: /* 0xab */
5064/* File: arm-vfp/OP_ADD_DOUBLE.S */
5065/* File: arm-vfp/fbinopWide.S */
5066    /*
5067     * Generic 64-bit double-precision floating point binary operation.
5068     * Provide an "instr" line that specifies an instruction that performs
5069     * "d2 = d0 op d1".
5070     *
5071     * for: add-double, sub-double, mul-double, div-double
5072     */
5073    /* doubleop 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    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5079    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5080    fldd    d1, [r3]                    @ d1<- vCC
5081    fldd    d0, [r2]                    @ d0<- vBB
5082
5083    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5084    faddd   d2, d0, d1                              @ s2<- op
5085    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5086    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5087    fstd    d2, [r9]                    @ vAA<- d2
5088    GOTO_OPCODE(ip)                     @ jump to next instruction
5089
5090
5091/* ------------------------------ */
5092    .balign 64
5093.L_OP_SUB_DOUBLE: /* 0xac */
5094/* File: arm-vfp/OP_SUB_DOUBLE.S */
5095/* File: arm-vfp/fbinopWide.S */
5096    /*
5097     * Generic 64-bit double-precision floating point binary operation.
5098     * Provide an "instr" line that specifies an instruction that performs
5099     * "d2 = d0 op d1".
5100     *
5101     * for: add-double, sub-double, mul-double, div-double
5102     */
5103    /* doubleop vAA, vBB, vCC */
5104    FETCH(r0, 1)                        @ r0<- CCBB
5105    mov     r9, rINST, lsr #8           @ r9<- AA
5106    mov     r3, r0, lsr #8              @ r3<- CC
5107    and     r2, r0, #255                @ r2<- BB
5108    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5109    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5110    fldd    d1, [r3]                    @ d1<- vCC
5111    fldd    d0, [r2]                    @ d0<- vBB
5112
5113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5114    fsubd   d2, d0, d1                              @ s2<- op
5115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5116    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5117    fstd    d2, [r9]                    @ vAA<- d2
5118    GOTO_OPCODE(ip)                     @ jump to next instruction
5119
5120
5121/* ------------------------------ */
5122    .balign 64
5123.L_OP_MUL_DOUBLE: /* 0xad */
5124/* File: arm-vfp/OP_MUL_DOUBLE.S */
5125/* File: arm-vfp/fbinopWide.S */
5126    /*
5127     * Generic 64-bit double-precision floating point binary operation.
5128     * Provide an "instr" line that specifies an instruction that performs
5129     * "d2 = d0 op d1".
5130     *
5131     * for: add-double, sub-double, mul-double, div-double
5132     */
5133    /* doubleop vAA, vBB, vCC */
5134    FETCH(r0, 1)                        @ r0<- CCBB
5135    mov     r9, rINST, lsr #8           @ r9<- AA
5136    mov     r3, r0, lsr #8              @ r3<- CC
5137    and     r2, r0, #255                @ r2<- BB
5138    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5139    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5140    fldd    d1, [r3]                    @ d1<- vCC
5141    fldd    d0, [r2]                    @ d0<- vBB
5142
5143    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5144    fmuld   d2, d0, d1                              @ s2<- op
5145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5146    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5147    fstd    d2, [r9]                    @ vAA<- d2
5148    GOTO_OPCODE(ip)                     @ jump to next instruction
5149
5150
5151/* ------------------------------ */
5152    .balign 64
5153.L_OP_DIV_DOUBLE: /* 0xae */
5154/* File: arm-vfp/OP_DIV_DOUBLE.S */
5155/* File: arm-vfp/fbinopWide.S */
5156    /*
5157     * Generic 64-bit double-precision floating point binary operation.
5158     * Provide an "instr" line that specifies an instruction that performs
5159     * "d2 = d0 op d1".
5160     *
5161     * for: add-double, sub-double, mul-double, div-double
5162     */
5163    /* doubleop vAA, vBB, vCC */
5164    FETCH(r0, 1)                        @ r0<- CCBB
5165    mov     r9, rINST, lsr #8           @ r9<- AA
5166    mov     r3, r0, lsr #8              @ r3<- CC
5167    and     r2, r0, #255                @ r2<- BB
5168    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5169    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5170    fldd    d1, [r3]                    @ d1<- vCC
5171    fldd    d0, [r2]                    @ d0<- vBB
5172
5173    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5174    fdivd   d2, d0, d1                              @ s2<- op
5175    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5176    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5177    fstd    d2, [r9]                    @ vAA<- d2
5178    GOTO_OPCODE(ip)                     @ jump to next instruction
5179
5180
5181/* ------------------------------ */
5182    .balign 64
5183.L_OP_REM_DOUBLE: /* 0xaf */
5184/* File: armv5te/OP_REM_DOUBLE.S */
5185/* EABI doesn't define a double remainder function, but libm does */
5186/* File: armv5te/binopWide.S */
5187    /*
5188     * Generic 64-bit binary operation.  Provide an "instr" line that
5189     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5190     * This could be an ARM instruction or a function call.  (If the result
5191     * comes back in a register other than r0, you can override "result".)
5192     *
5193     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5194     * vCC (r1).  Useful for integer division and modulus.
5195     *
5196     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5197     *      xor-long, add-double, sub-double, mul-double, div-double,
5198     *      rem-double
5199     *
5200     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5201     */
5202    /* binop vAA, vBB, vCC */
5203    FETCH(r0, 1)                        @ r0<- CCBB
5204    mov     r9, rINST, lsr #8           @ r9<- AA
5205    and     r2, r0, #255                @ r2<- BB
5206    mov     r3, r0, lsr #8              @ r3<- CC
5207    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5208    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5209    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5210    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5211    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5212    .if 0
5213    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5214    beq     common_errDivideByZero
5215    .endif
5216    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5217
5218                               @ optional op; may set condition codes
5219    bl      fmod                              @ result<- op, r0-r3 changed
5220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5221    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5222    GOTO_OPCODE(ip)                     @ jump to next instruction
5223    /* 14-17 instructions */
5224
5225
5226/* ------------------------------ */
5227    .balign 64
5228.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5229/* File: armv6t2/OP_ADD_INT_2ADDR.S */
5230/* File: armv6t2/binop2addr.S */
5231    /*
5232     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5233     * that specifies an instruction that performs "result = r0 op r1".
5234     * This could be an ARM instruction or a function call.  (If the result
5235     * comes back in a register other than r0, you can override "result".)
5236     *
5237     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5238     * vCC (r1).  Useful for integer division and modulus.
5239     *
5240     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5241     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5242     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5243     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5244     */
5245    /* binop/2addr vA, vB */
5246    mov     r3, rINST, lsr #12          @ r3<- B
5247    ubfx    r9, rINST, #8, #4           @ r9<- A
5248    GET_VREG(r1, r3)                    @ r1<- vB
5249    GET_VREG(r0, r9)                    @ r0<- vA
5250    .if 0
5251    cmp     r1, #0                      @ is second operand zero?
5252    beq     common_errDivideByZero
5253    .endif
5254    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5255
5256                               @ optional op; may set condition codes
5257    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5259    SET_VREG(r0, r9)               @ vAA<- r0
5260    GOTO_OPCODE(ip)                     @ jump to next instruction
5261    /* 10-13 instructions */
5262
5263
5264/* ------------------------------ */
5265    .balign 64
5266.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5267/* File: armv6t2/OP_SUB_INT_2ADDR.S */
5268/* File: armv6t2/binop2addr.S */
5269    /*
5270     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5271     * that specifies an instruction that performs "result = r0 op r1".
5272     * This could be an ARM instruction or a function call.  (If the result
5273     * comes back in a register other than r0, you can override "result".)
5274     *
5275     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5276     * vCC (r1).  Useful for integer division and modulus.
5277     *
5278     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5279     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5280     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5281     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5282     */
5283    /* binop/2addr vA, vB */
5284    mov     r3, rINST, lsr #12          @ r3<- B
5285    ubfx    r9, rINST, #8, #4           @ r9<- A
5286    GET_VREG(r1, r3)                    @ r1<- vB
5287    GET_VREG(r0, r9)                    @ r0<- vA
5288    .if 0
5289    cmp     r1, #0                      @ is second operand zero?
5290    beq     common_errDivideByZero
5291    .endif
5292    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5293
5294                               @ optional op; may set condition codes
5295    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5297    SET_VREG(r0, r9)               @ vAA<- r0
5298    GOTO_OPCODE(ip)                     @ jump to next instruction
5299    /* 10-13 instructions */
5300
5301
5302/* ------------------------------ */
5303    .balign 64
5304.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5305/* File: armv6t2/OP_MUL_INT_2ADDR.S */
5306/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5307/* File: armv6t2/binop2addr.S */
5308    /*
5309     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5310     * that specifies an instruction that performs "result = r0 op r1".
5311     * This could be an ARM instruction or a function call.  (If the result
5312     * comes back in a register other than r0, you can override "result".)
5313     *
5314     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5315     * vCC (r1).  Useful for integer division and modulus.
5316     *
5317     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5318     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5319     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5320     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5321     */
5322    /* binop/2addr vA, vB */
5323    mov     r3, rINST, lsr #12          @ r3<- B
5324    ubfx    r9, rINST, #8, #4           @ r9<- A
5325    GET_VREG(r1, r3)                    @ r1<- vB
5326    GET_VREG(r0, r9)                    @ r0<- vA
5327    .if 0
5328    cmp     r1, #0                      @ is second operand zero?
5329    beq     common_errDivideByZero
5330    .endif
5331    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5332
5333                               @ optional op; may set condition codes
5334    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5336    SET_VREG(r0, r9)               @ vAA<- r0
5337    GOTO_OPCODE(ip)                     @ jump to next instruction
5338    /* 10-13 instructions */
5339
5340
5341/* ------------------------------ */
5342    .balign 64
5343.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5344/* File: armv6t2/OP_DIV_INT_2ADDR.S */
5345/* File: armv6t2/binop2addr.S */
5346    /*
5347     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5348     * that specifies an instruction that performs "result = r0 op r1".
5349     * This could be an ARM instruction or a function call.  (If the result
5350     * comes back in a register other than r0, you can override "result".)
5351     *
5352     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5353     * vCC (r1).  Useful for integer division and modulus.
5354     *
5355     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5356     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5357     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5358     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5359     */
5360    /* binop/2addr vA, vB */
5361    mov     r3, rINST, lsr #12          @ r3<- B
5362    ubfx    r9, rINST, #8, #4           @ r9<- A
5363    GET_VREG(r1, r3)                    @ r1<- vB
5364    GET_VREG(r0, r9)                    @ r0<- vA
5365    .if 1
5366    cmp     r1, #0                      @ is second operand zero?
5367    beq     common_errDivideByZero
5368    .endif
5369    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5370
5371                               @ optional op; may set condition codes
5372    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5373    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5374    SET_VREG(r0, r9)               @ vAA<- r0
5375    GOTO_OPCODE(ip)                     @ jump to next instruction
5376    /* 10-13 instructions */
5377
5378
5379/* ------------------------------ */
5380    .balign 64
5381.L_OP_REM_INT_2ADDR: /* 0xb4 */
5382/* File: armv6t2/OP_REM_INT_2ADDR.S */
5383/* idivmod returns quotient in r0 and remainder in r1 */
5384/* File: armv6t2/binop2addr.S */
5385    /*
5386     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5387     * that specifies an instruction that performs "result = r0 op r1".
5388     * This could be an ARM instruction or a function call.  (If the result
5389     * comes back in a register other than r0, you can override "result".)
5390     *
5391     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5392     * vCC (r1).  Useful for integer division and modulus.
5393     *
5394     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5395     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5396     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5397     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5398     */
5399    /* binop/2addr vA, vB */
5400    mov     r3, rINST, lsr #12          @ r3<- B
5401    ubfx    r9, rINST, #8, #4           @ r9<- A
5402    GET_VREG(r1, r3)                    @ r1<- vB
5403    GET_VREG(r0, r9)                    @ r0<- vA
5404    .if 1
5405    cmp     r1, #0                      @ is second operand zero?
5406    beq     common_errDivideByZero
5407    .endif
5408    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5409
5410                               @ optional op; may set condition codes
5411    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5412    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5413    SET_VREG(r1, r9)               @ vAA<- r1
5414    GOTO_OPCODE(ip)                     @ jump to next instruction
5415    /* 10-13 instructions */
5416
5417
5418/* ------------------------------ */
5419    .balign 64
5420.L_OP_AND_INT_2ADDR: /* 0xb5 */
5421/* File: armv6t2/OP_AND_INT_2ADDR.S */
5422/* File: armv6t2/binop2addr.S */
5423    /*
5424     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5425     * that specifies an instruction that performs "result = r0 op r1".
5426     * This could be an ARM instruction or a function call.  (If the result
5427     * comes back in a register other than r0, you can override "result".)
5428     *
5429     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5430     * vCC (r1).  Useful for integer division and modulus.
5431     *
5432     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5433     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5434     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5435     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5436     */
5437    /* binop/2addr vA, vB */
5438    mov     r3, rINST, lsr #12          @ r3<- B
5439    ubfx    r9, rINST, #8, #4           @ r9<- A
5440    GET_VREG(r1, r3)                    @ r1<- vB
5441    GET_VREG(r0, r9)                    @ r0<- vA
5442    .if 0
5443    cmp     r1, #0                      @ is second operand zero?
5444    beq     common_errDivideByZero
5445    .endif
5446    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5447
5448                               @ optional op; may set condition codes
5449    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5450    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5451    SET_VREG(r0, r9)               @ vAA<- r0
5452    GOTO_OPCODE(ip)                     @ jump to next instruction
5453    /* 10-13 instructions */
5454
5455
5456/* ------------------------------ */
5457    .balign 64
5458.L_OP_OR_INT_2ADDR: /* 0xb6 */
5459/* File: armv6t2/OP_OR_INT_2ADDR.S */
5460/* File: armv6t2/binop2addr.S */
5461    /*
5462     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5463     * that specifies an instruction that performs "result = r0 op r1".
5464     * This could be an ARM instruction or a function call.  (If the result
5465     * comes back in a register other than r0, you can override "result".)
5466     *
5467     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5468     * vCC (r1).  Useful for integer division and modulus.
5469     *
5470     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5471     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5472     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5473     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5474     */
5475    /* binop/2addr vA, vB */
5476    mov     r3, rINST, lsr #12          @ r3<- B
5477    ubfx    r9, rINST, #8, #4           @ r9<- A
5478    GET_VREG(r1, r3)                    @ r1<- vB
5479    GET_VREG(r0, r9)                    @ r0<- vA
5480    .if 0
5481    cmp     r1, #0                      @ is second operand zero?
5482    beq     common_errDivideByZero
5483    .endif
5484    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5485
5486                               @ optional op; may set condition codes
5487    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5488    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5489    SET_VREG(r0, r9)               @ vAA<- r0
5490    GOTO_OPCODE(ip)                     @ jump to next instruction
5491    /* 10-13 instructions */
5492
5493
5494/* ------------------------------ */
5495    .balign 64
5496.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5497/* File: armv6t2/OP_XOR_INT_2ADDR.S */
5498/* File: armv6t2/binop2addr.S */
5499    /*
5500     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5501     * that specifies an instruction that performs "result = r0 op r1".
5502     * This could be an ARM instruction or a function call.  (If the result
5503     * comes back in a register other than r0, you can override "result".)
5504     *
5505     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5506     * vCC (r1).  Useful for integer division and modulus.
5507     *
5508     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5509     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5510     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5511     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5512     */
5513    /* binop/2addr vA, vB */
5514    mov     r3, rINST, lsr #12          @ r3<- B
5515    ubfx    r9, rINST, #8, #4           @ r9<- A
5516    GET_VREG(r1, r3)                    @ r1<- vB
5517    GET_VREG(r0, r9)                    @ r0<- vA
5518    .if 0
5519    cmp     r1, #0                      @ is second operand zero?
5520    beq     common_errDivideByZero
5521    .endif
5522    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5523
5524                               @ optional op; may set condition codes
5525    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5526    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5527    SET_VREG(r0, r9)               @ vAA<- r0
5528    GOTO_OPCODE(ip)                     @ jump to next instruction
5529    /* 10-13 instructions */
5530
5531
5532/* ------------------------------ */
5533    .balign 64
5534.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5535/* File: armv6t2/OP_SHL_INT_2ADDR.S */
5536/* File: armv6t2/binop2addr.S */
5537    /*
5538     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5539     * that specifies an instruction that performs "result = r0 op r1".
5540     * This could be an ARM instruction or a function call.  (If the result
5541     * comes back in a register other than r0, you can override "result".)
5542     *
5543     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5544     * vCC (r1).  Useful for integer division and modulus.
5545     *
5546     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5547     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5548     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5549     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5550     */
5551    /* binop/2addr vA, vB */
5552    mov     r3, rINST, lsr #12          @ r3<- B
5553    ubfx    r9, rINST, #8, #4           @ r9<- A
5554    GET_VREG(r1, r3)                    @ r1<- vB
5555    GET_VREG(r0, r9)                    @ r0<- vA
5556    .if 0
5557    cmp     r1, #0                      @ is second operand zero?
5558    beq     common_errDivideByZero
5559    .endif
5560    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5561
5562    and     r1, r1, #31                           @ optional op; may set condition codes
5563    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5565    SET_VREG(r0, r9)               @ vAA<- r0
5566    GOTO_OPCODE(ip)                     @ jump to next instruction
5567    /* 10-13 instructions */
5568
5569
5570/* ------------------------------ */
5571    .balign 64
5572.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5573/* File: armv6t2/OP_SHR_INT_2ADDR.S */
5574/* File: armv6t2/binop2addr.S */
5575    /*
5576     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5577     * that specifies an instruction that performs "result = r0 op r1".
5578     * This could be an ARM instruction or a function call.  (If the result
5579     * comes back in a register other than r0, you can override "result".)
5580     *
5581     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5582     * vCC (r1).  Useful for integer division and modulus.
5583     *
5584     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5585     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5586     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5587     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5588     */
5589    /* binop/2addr vA, vB */
5590    mov     r3, rINST, lsr #12          @ r3<- B
5591    ubfx    r9, rINST, #8, #4           @ r9<- A
5592    GET_VREG(r1, r3)                    @ r1<- vB
5593    GET_VREG(r0, r9)                    @ r0<- vA
5594    .if 0
5595    cmp     r1, #0                      @ is second operand zero?
5596    beq     common_errDivideByZero
5597    .endif
5598    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5599
5600    and     r1, r1, #31                           @ optional op; may set condition codes
5601    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5602    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5603    SET_VREG(r0, r9)               @ vAA<- r0
5604    GOTO_OPCODE(ip)                     @ jump to next instruction
5605    /* 10-13 instructions */
5606
5607
5608/* ------------------------------ */
5609    .balign 64
5610.L_OP_USHR_INT_2ADDR: /* 0xba */
5611/* File: armv6t2/OP_USHR_INT_2ADDR.S */
5612/* File: armv6t2/binop2addr.S */
5613    /*
5614     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5615     * that specifies an instruction that performs "result = r0 op r1".
5616     * This could be an ARM instruction or a function call.  (If the result
5617     * comes back in a register other than r0, you can override "result".)
5618     *
5619     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5620     * vCC (r1).  Useful for integer division and modulus.
5621     *
5622     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5623     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5624     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5625     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5626     */
5627    /* binop/2addr vA, vB */
5628    mov     r3, rINST, lsr #12          @ r3<- B
5629    ubfx    r9, rINST, #8, #4           @ r9<- A
5630    GET_VREG(r1, r3)                    @ r1<- vB
5631    GET_VREG(r0, r9)                    @ r0<- vA
5632    .if 0
5633    cmp     r1, #0                      @ is second operand zero?
5634    beq     common_errDivideByZero
5635    .endif
5636    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5637
5638    and     r1, r1, #31                           @ optional op; may set condition codes
5639    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5640    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5641    SET_VREG(r0, r9)               @ vAA<- r0
5642    GOTO_OPCODE(ip)                     @ jump to next instruction
5643    /* 10-13 instructions */
5644
5645
5646/* ------------------------------ */
5647    .balign 64
5648.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5649/* File: armv6t2/OP_ADD_LONG_2ADDR.S */
5650/* File: armv6t2/binopWide2addr.S */
5651    /*
5652     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5653     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5654     * This could be an ARM instruction or a function call.  (If the result
5655     * comes back in a register other than r0, you can override "result".)
5656     *
5657     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5658     * vCC (r1).  Useful for integer division and modulus.
5659     *
5660     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5661     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5662     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5663     *      rem-double/2addr
5664     */
5665    /* binop/2addr vA, vB */
5666    mov     r1, rINST, lsr #12          @ r1<- B
5667    ubfx    r9, rINST, #8, #4           @ r9<- A
5668    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5669    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5670    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5671    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5672    .if 0
5673    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5674    beq     common_errDivideByZero
5675    .endif
5676    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5677
5678    adds    r0, r0, r2                           @ optional op; may set condition codes
5679    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5680    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5681    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5682    GOTO_OPCODE(ip)                     @ jump to next instruction
5683    /* 12-15 instructions */
5684
5685
5686/* ------------------------------ */
5687    .balign 64
5688.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5689/* File: armv6t2/OP_SUB_LONG_2ADDR.S */
5690/* File: armv6t2/binopWide2addr.S */
5691    /*
5692     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5693     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5694     * This could be an ARM instruction or a function call.  (If the result
5695     * comes back in a register other than r0, you can override "result".)
5696     *
5697     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5698     * vCC (r1).  Useful for integer division and modulus.
5699     *
5700     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5701     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5702     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5703     *      rem-double/2addr
5704     */
5705    /* binop/2addr vA, vB */
5706    mov     r1, rINST, lsr #12          @ r1<- B
5707    ubfx    r9, rINST, #8, #4           @ r9<- A
5708    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5709    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5710    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5711    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5712    .if 0
5713    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5714    beq     common_errDivideByZero
5715    .endif
5716    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5717
5718    subs    r0, r0, r2                           @ optional op; may set condition codes
5719    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5720    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5721    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5722    GOTO_OPCODE(ip)                     @ jump to next instruction
5723    /* 12-15 instructions */
5724
5725
5726/* ------------------------------ */
5727    .balign 64
5728.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5729/* File: armv6t2/OP_MUL_LONG_2ADDR.S */
5730    /*
5731     * Signed 64-bit integer multiply, "/2addr" version.
5732     *
5733     * See OP_MUL_LONG for an explanation.
5734     *
5735     * We get a little tight on registers, so to avoid looking up &fp[A]
5736     * again we stuff it into rINST.
5737     */
5738    /* mul-long/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     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5743    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5744    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5745    mul     ip, r2, r1                  @  ip<- ZxW
5746    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5747    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5748    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5749    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5750    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5751    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5752    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5753    GOTO_OPCODE(ip)                     @ jump to next instruction
5754
5755/* ------------------------------ */
5756    .balign 64
5757.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5758/* File: armv6t2/OP_DIV_LONG_2ADDR.S */
5759/* File: armv6t2/binopWide2addr.S */
5760    /*
5761     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5762     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5763     * This could be an ARM instruction or a function call.  (If the result
5764     * comes back in a register other than r0, you can override "result".)
5765     *
5766     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5767     * vCC (r1).  Useful for integer division and modulus.
5768     *
5769     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5770     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5771     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5772     *      rem-double/2addr
5773     */
5774    /* binop/2addr vA, vB */
5775    mov     r1, rINST, lsr #12          @ r1<- B
5776    ubfx    r9, rINST, #8, #4           @ r9<- A
5777    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5778    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5779    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5780    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5781    .if 1
5782    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5783    beq     common_errDivideByZero
5784    .endif
5785    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5786
5787                               @ optional op; may set condition codes
5788    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5789    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5790    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5791    GOTO_OPCODE(ip)                     @ jump to next instruction
5792    /* 12-15 instructions */
5793
5794
5795/* ------------------------------ */
5796    .balign 64
5797.L_OP_REM_LONG_2ADDR: /* 0xbf */
5798/* File: armv6t2/OP_REM_LONG_2ADDR.S */
5799/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5800/* File: armv6t2/binopWide2addr.S */
5801    /*
5802     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5803     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5804     * This could be an ARM instruction or a function call.  (If the result
5805     * comes back in a register other than r0, you can override "result".)
5806     *
5807     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5808     * vCC (r1).  Useful for integer division and modulus.
5809     *
5810     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5811     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5812     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5813     *      rem-double/2addr
5814     */
5815    /* binop/2addr vA, vB */
5816    mov     r1, rINST, lsr #12          @ r1<- B
5817    ubfx    r9, rINST, #8, #4           @ r9<- A
5818    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5819    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5820    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5821    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5822    .if 1
5823    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5824    beq     common_errDivideByZero
5825    .endif
5826    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5827
5828                               @ optional op; may set condition codes
5829    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5831    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5832    GOTO_OPCODE(ip)                     @ jump to next instruction
5833    /* 12-15 instructions */
5834
5835
5836/* ------------------------------ */
5837    .balign 64
5838.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5839/* File: armv6t2/OP_AND_LONG_2ADDR.S */
5840/* File: armv6t2/binopWide2addr.S */
5841    /*
5842     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5843     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5844     * This could be an ARM instruction or a function call.  (If the result
5845     * comes back in a register other than r0, you can override "result".)
5846     *
5847     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5848     * vCC (r1).  Useful for integer division and modulus.
5849     *
5850     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5851     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5852     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5853     *      rem-double/2addr
5854     */
5855    /* binop/2addr vA, vB */
5856    mov     r1, rINST, lsr #12          @ r1<- B
5857    ubfx    r9, rINST, #8, #4           @ r9<- A
5858    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5859    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5860    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5861    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5862    .if 0
5863    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5864    beq     common_errDivideByZero
5865    .endif
5866    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5867
5868    and     r0, r0, r2                           @ optional op; may set condition codes
5869    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5871    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5872    GOTO_OPCODE(ip)                     @ jump to next instruction
5873    /* 12-15 instructions */
5874
5875
5876/* ------------------------------ */
5877    .balign 64
5878.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5879/* File: armv6t2/OP_OR_LONG_2ADDR.S */
5880/* File: armv6t2/binopWide2addr.S */
5881    /*
5882     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5883     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5884     * This could be an ARM instruction or a function call.  (If the result
5885     * comes back in a register other than r0, you can override "result".)
5886     *
5887     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5888     * vCC (r1).  Useful for integer division and modulus.
5889     *
5890     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5891     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5892     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5893     *      rem-double/2addr
5894     */
5895    /* binop/2addr vA, vB */
5896    mov     r1, rINST, lsr #12          @ r1<- B
5897    ubfx    r9, rINST, #8, #4           @ r9<- A
5898    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5899    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5900    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5901    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5902    .if 0
5903    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5904    beq     common_errDivideByZero
5905    .endif
5906    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5907
5908    orr     r0, r0, r2                           @ optional op; may set condition codes
5909    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5911    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5912    GOTO_OPCODE(ip)                     @ jump to next instruction
5913    /* 12-15 instructions */
5914
5915
5916/* ------------------------------ */
5917    .balign 64
5918.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5919/* File: armv6t2/OP_XOR_LONG_2ADDR.S */
5920/* File: armv6t2/binopWide2addr.S */
5921    /*
5922     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5923     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5924     * This could be an ARM instruction or a function call.  (If the result
5925     * comes back in a register other than r0, you can override "result".)
5926     *
5927     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5928     * vCC (r1).  Useful for integer division and modulus.
5929     *
5930     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5931     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5932     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5933     *      rem-double/2addr
5934     */
5935    /* binop/2addr vA, vB */
5936    mov     r1, rINST, lsr #12          @ r1<- B
5937    ubfx    r9, rINST, #8, #4           @ r9<- A
5938    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5939    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5940    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5941    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5942    .if 0
5943    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5944    beq     common_errDivideByZero
5945    .endif
5946    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5947
5948    eor     r0, r0, r2                           @ optional op; may set condition codes
5949    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5950    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5951    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5952    GOTO_OPCODE(ip)                     @ jump to next instruction
5953    /* 12-15 instructions */
5954
5955
5956/* ------------------------------ */
5957    .balign 64
5958.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
5959/* File: armv6t2/OP_SHL_LONG_2ADDR.S */
5960    /*
5961     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5962     * 32-bit shift distance.
5963     */
5964    /* shl-long/2addr vA, vB */
5965    mov     r3, rINST, lsr #12          @ r3<- B
5966    ubfx    r9, rINST, #8, #4           @ r9<- A
5967    GET_VREG(r2, r3)                    @ r2<- vB
5968    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5969    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5970    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5971
5972    mov     r1, r1, asl r2              @  r1<- r1 << r2
5973    rsb     r3, r2, #32                 @  r3<- 32 - r2
5974    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5975    subs    ip, r2, #32                 @  ip<- r2 - 32
5976    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5977    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5978    mov     r0, r0, asl r2              @  r0<- r0 << r2
5979    b       .LOP_SHL_LONG_2ADDR_finish
5980
5981/* ------------------------------ */
5982    .balign 64
5983.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
5984/* File: armv6t2/OP_SHR_LONG_2ADDR.S */
5985    /*
5986     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
5987     * 32-bit shift distance.
5988     */
5989    /* shr-long/2addr vA, vB */
5990    mov     r3, rINST, lsr #12          @ r3<- B
5991    ubfx    r9, rINST, #8, #4           @ r9<- A
5992    GET_VREG(r2, r3)                    @ r2<- vB
5993    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5994    and     r2, r2, #63                 @ r2<- r2 & 0x3f
5995    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5996
5997    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5998    rsb     r3, r2, #32                 @  r3<- 32 - r2
5999    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6000    subs    ip, r2, #32                 @  ip<- r2 - 32
6001    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6002    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6003    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6004    b       .LOP_SHR_LONG_2ADDR_finish
6005
6006/* ------------------------------ */
6007    .balign 64
6008.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6009/* File: armv6t2/OP_USHR_LONG_2ADDR.S */
6010    /*
6011     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6012     * 32-bit shift distance.
6013     */
6014    /* ushr-long/2addr vA, vB */
6015    mov     r3, rINST, lsr #12          @ r3<- B
6016    ubfx    r9, rINST, #8, #4           @ r9<- A
6017    GET_VREG(r2, r3)                    @ r2<- vB
6018    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6019    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6020    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6021
6022    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6023    rsb     r3, r2, #32                 @  r3<- 32 - r2
6024    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6025    subs    ip, r2, #32                 @  ip<- r2 - 32
6026    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6027    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6028    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6029    b       .LOP_USHR_LONG_2ADDR_finish
6030
6031/* ------------------------------ */
6032    .balign 64
6033.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6034/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6035/* File: arm-vfp/fbinop2addr.S */
6036    /*
6037     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6038     * an "instr" line that specifies an instruction that performs
6039     * "s2 = s0 op s1".
6040     *
6041     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6042     */
6043    /* binop/2addr vA, vB */
6044    mov     r3, rINST, lsr #12          @ r3<- B
6045    mov     r9, rINST, lsr #8           @ r9<- A+
6046    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6047    and     r9, r9, #15                 @ r9<- A
6048    flds    s1, [r3]                    @ s1<- vB
6049    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6050    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6051    flds    s0, [r9]                    @ s0<- vA
6052
6053    fadds   s2, s0, s1                              @ s2<- op
6054    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6055    fsts    s2, [r9]                    @ vAA<- s2
6056    GOTO_OPCODE(ip)                     @ jump to next instruction
6057
6058
6059/* ------------------------------ */
6060    .balign 64
6061.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6062/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6063/* File: arm-vfp/fbinop2addr.S */
6064    /*
6065     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6066     * an "instr" line that specifies an instruction that performs
6067     * "s2 = s0 op s1".
6068     *
6069     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6070     */
6071    /* binop/2addr vA, vB */
6072    mov     r3, rINST, lsr #12          @ r3<- B
6073    mov     r9, rINST, lsr #8           @ r9<- A+
6074    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6075    and     r9, r9, #15                 @ r9<- A
6076    flds    s1, [r3]                    @ s1<- vB
6077    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6078    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6079    flds    s0, [r9]                    @ s0<- vA
6080
6081    fsubs   s2, s0, s1                              @ s2<- op
6082    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6083    fsts    s2, [r9]                    @ vAA<- s2
6084    GOTO_OPCODE(ip)                     @ jump to next instruction
6085
6086
6087/* ------------------------------ */
6088    .balign 64
6089.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6090/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6091/* File: arm-vfp/fbinop2addr.S */
6092    /*
6093     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6094     * an "instr" line that specifies an instruction that performs
6095     * "s2 = s0 op s1".
6096     *
6097     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6098     */
6099    /* binop/2addr vA, vB */
6100    mov     r3, rINST, lsr #12          @ r3<- B
6101    mov     r9, rINST, lsr #8           @ r9<- A+
6102    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6103    and     r9, r9, #15                 @ r9<- A
6104    flds    s1, [r3]                    @ s1<- vB
6105    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6106    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6107    flds    s0, [r9]                    @ s0<- vA
6108
6109    fmuls   s2, s0, s1                              @ s2<- op
6110    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6111    fsts    s2, [r9]                    @ vAA<- s2
6112    GOTO_OPCODE(ip)                     @ jump to next instruction
6113
6114
6115/* ------------------------------ */
6116    .balign 64
6117.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6118/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6119/* File: arm-vfp/fbinop2addr.S */
6120    /*
6121     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6122     * an "instr" line that specifies an instruction that performs
6123     * "s2 = s0 op s1".
6124     *
6125     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6126     */
6127    /* binop/2addr vA, vB */
6128    mov     r3, rINST, lsr #12          @ r3<- B
6129    mov     r9, rINST, lsr #8           @ r9<- A+
6130    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6131    and     r9, r9, #15                 @ r9<- A
6132    flds    s1, [r3]                    @ s1<- vB
6133    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6134    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6135    flds    s0, [r9]                    @ s0<- vA
6136
6137    fdivs   s2, s0, s1                              @ s2<- op
6138    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6139    fsts    s2, [r9]                    @ vAA<- s2
6140    GOTO_OPCODE(ip)                     @ jump to next instruction
6141
6142
6143/* ------------------------------ */
6144    .balign 64
6145.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6146/* File: armv6t2/OP_REM_FLOAT_2ADDR.S */
6147/* EABI doesn't define a float remainder function, but libm does */
6148/* File: armv6t2/binop2addr.S */
6149    /*
6150     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6151     * that specifies an instruction that performs "result = r0 op r1".
6152     * This could be an ARM instruction or a function call.  (If the result
6153     * comes back in a register other than r0, you can override "result".)
6154     *
6155     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6156     * vCC (r1).  Useful for integer division and modulus.
6157     *
6158     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6159     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6160     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6161     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6162     */
6163    /* binop/2addr vA, vB */
6164    mov     r3, rINST, lsr #12          @ r3<- B
6165    ubfx    r9, rINST, #8, #4           @ r9<- A
6166    GET_VREG(r1, r3)                    @ r1<- vB
6167    GET_VREG(r0, r9)                    @ r0<- vA
6168    .if 0
6169    cmp     r1, #0                      @ is second operand zero?
6170    beq     common_errDivideByZero
6171    .endif
6172    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6173
6174                               @ optional op; may set condition codes
6175    bl      fmodf                              @ r0<- op, r0-r3 changed
6176    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6177    SET_VREG(r0, r9)               @ vAA<- r0
6178    GOTO_OPCODE(ip)                     @ jump to next instruction
6179    /* 10-13 instructions */
6180
6181
6182/* ------------------------------ */
6183    .balign 64
6184.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6185/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6186/* File: arm-vfp/fbinopWide2addr.S */
6187    /*
6188     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6189     * an "instr" line that specifies an instruction that performs
6190     * "d2 = d0 op d1".
6191     *
6192     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6193     *      div-double/2addr
6194     */
6195    /* binop/2addr vA, vB */
6196    mov     r3, rINST, lsr #12          @ r3<- B
6197    mov     r9, rINST, lsr #8           @ r9<- A+
6198    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6199    and     r9, r9, #15                 @ r9<- A
6200    fldd    d1, [r3]                    @ d1<- vB
6201    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6202    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6203    fldd    d0, [r9]                    @ d0<- vA
6204
6205    faddd   d2, d0, d1                              @ d2<- op
6206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6207    fstd    d2, [r9]                    @ vAA<- d2
6208    GOTO_OPCODE(ip)                     @ jump to next instruction
6209
6210
6211/* ------------------------------ */
6212    .balign 64
6213.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6214/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6215/* File: arm-vfp/fbinopWide2addr.S */
6216    /*
6217     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6218     * an "instr" line that specifies an instruction that performs
6219     * "d2 = d0 op d1".
6220     *
6221     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6222     *      div-double/2addr
6223     */
6224    /* binop/2addr vA, vB */
6225    mov     r3, rINST, lsr #12          @ r3<- B
6226    mov     r9, rINST, lsr #8           @ r9<- A+
6227    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6228    and     r9, r9, #15                 @ r9<- A
6229    fldd    d1, [r3]                    @ d1<- vB
6230    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6231    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6232    fldd    d0, [r9]                    @ d0<- vA
6233
6234    fsubd   d2, d0, d1                              @ d2<- op
6235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6236    fstd    d2, [r9]                    @ vAA<- d2
6237    GOTO_OPCODE(ip)                     @ jump to next instruction
6238
6239
6240/* ------------------------------ */
6241    .balign 64
6242.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6243/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6244/* File: arm-vfp/fbinopWide2addr.S */
6245    /*
6246     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6247     * an "instr" line that specifies an instruction that performs
6248     * "d2 = d0 op d1".
6249     *
6250     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6251     *      div-double/2addr
6252     */
6253    /* binop/2addr vA, vB */
6254    mov     r3, rINST, lsr #12          @ r3<- B
6255    mov     r9, rINST, lsr #8           @ r9<- A+
6256    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6257    and     r9, r9, #15                 @ r9<- A
6258    fldd    d1, [r3]                    @ d1<- vB
6259    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6260    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6261    fldd    d0, [r9]                    @ d0<- vA
6262
6263    fmuld   d2, d0, d1                              @ d2<- op
6264    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6265    fstd    d2, [r9]                    @ vAA<- d2
6266    GOTO_OPCODE(ip)                     @ jump to next instruction
6267
6268
6269/* ------------------------------ */
6270    .balign 64
6271.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6272/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6273/* File: arm-vfp/fbinopWide2addr.S */
6274    /*
6275     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6276     * an "instr" line that specifies an instruction that performs
6277     * "d2 = d0 op d1".
6278     *
6279     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6280     *      div-double/2addr
6281     */
6282    /* binop/2addr vA, vB */
6283    mov     r3, rINST, lsr #12          @ r3<- B
6284    mov     r9, rINST, lsr #8           @ r9<- A+
6285    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6286    and     r9, r9, #15                 @ r9<- A
6287    fldd    d1, [r3]                    @ d1<- vB
6288    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6289    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6290    fldd    d0, [r9]                    @ d0<- vA
6291
6292    fdivd   d2, d0, d1                              @ d2<- op
6293    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6294    fstd    d2, [r9]                    @ vAA<- d2
6295    GOTO_OPCODE(ip)                     @ jump to next instruction
6296
6297
6298/* ------------------------------ */
6299    .balign 64
6300.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6301/* File: armv6t2/OP_REM_DOUBLE_2ADDR.S */
6302/* EABI doesn't define a double remainder function, but libm does */
6303/* File: armv6t2/binopWide2addr.S */
6304    /*
6305     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6306     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6307     * This could be an ARM instruction or a function call.  (If the result
6308     * comes back in a register other than r0, you can override "result".)
6309     *
6310     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6311     * vCC (r1).  Useful for integer division and modulus.
6312     *
6313     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6314     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6315     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6316     *      rem-double/2addr
6317     */
6318    /* binop/2addr vA, vB */
6319    mov     r1, rINST, lsr #12          @ r1<- B
6320    ubfx    r9, rINST, #8, #4           @ r9<- A
6321    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6322    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6323    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6324    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6325    .if 0
6326    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6327    beq     common_errDivideByZero
6328    .endif
6329    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6330
6331                               @ optional op; may set condition codes
6332    bl      fmod                              @ result<- op, r0-r3 changed
6333    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6334    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6335    GOTO_OPCODE(ip)                     @ jump to next instruction
6336    /* 12-15 instructions */
6337
6338
6339/* ------------------------------ */
6340    .balign 64
6341.L_OP_ADD_INT_LIT16: /* 0xd0 */
6342/* File: armv6t2/OP_ADD_INT_LIT16.S */
6343/* File: armv6t2/binopLit16.S */
6344    /*
6345     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6346     * that specifies an instruction that performs "result = r0 op r1".
6347     * This could be an ARM instruction or a function call.  (If the result
6348     * comes back in a register other than r0, you can override "result".)
6349     *
6350     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6351     * vCC (r1).  Useful for integer division and modulus.
6352     *
6353     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6354     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6355     */
6356    /* binop/lit16 vA, vB, #+CCCC */
6357    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6358    mov     r2, rINST, lsr #12          @ r2<- B
6359    ubfx    r9, rINST, #8, #4           @ r9<- A
6360    GET_VREG(r0, r2)                    @ r0<- vB
6361    .if 0
6362    cmp     r1, #0                      @ is second operand zero?
6363    beq     common_errDivideByZero
6364    .endif
6365    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6366
6367    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6368    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6369    SET_VREG(r0, r9)               @ vAA<- r0
6370    GOTO_OPCODE(ip)                     @ jump to next instruction
6371    /* 10-13 instructions */
6372
6373
6374/* ------------------------------ */
6375    .balign 64
6376.L_OP_RSUB_INT: /* 0xd1 */
6377/* File: armv6t2/OP_RSUB_INT.S */
6378/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6379/* File: armv6t2/binopLit16.S */
6380    /*
6381     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6382     * that specifies an instruction that performs "result = r0 op r1".
6383     * This could be an ARM instruction or a function call.  (If the result
6384     * comes back in a register other than r0, you can override "result".)
6385     *
6386     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6387     * vCC (r1).  Useful for integer division and modulus.
6388     *
6389     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6390     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6391     */
6392    /* binop/lit16 vA, vB, #+CCCC */
6393    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6394    mov     r2, rINST, lsr #12          @ r2<- B
6395    ubfx    r9, rINST, #8, #4           @ r9<- A
6396    GET_VREG(r0, r2)                    @ r0<- vB
6397    .if 0
6398    cmp     r1, #0                      @ is second operand zero?
6399    beq     common_errDivideByZero
6400    .endif
6401    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6402
6403    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6404    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6405    SET_VREG(r0, r9)               @ vAA<- r0
6406    GOTO_OPCODE(ip)                     @ jump to next instruction
6407    /* 10-13 instructions */
6408
6409
6410/* ------------------------------ */
6411    .balign 64
6412.L_OP_MUL_INT_LIT16: /* 0xd2 */
6413/* File: armv6t2/OP_MUL_INT_LIT16.S */
6414/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6415/* File: armv6t2/binopLit16.S */
6416    /*
6417     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6418     * that specifies an instruction that performs "result = r0 op r1".
6419     * This could be an ARM instruction or a function call.  (If the result
6420     * comes back in a register other than r0, you can override "result".)
6421     *
6422     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6423     * vCC (r1).  Useful for integer division and modulus.
6424     *
6425     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6426     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6427     */
6428    /* binop/lit16 vA, vB, #+CCCC */
6429    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6430    mov     r2, rINST, lsr #12          @ r2<- B
6431    ubfx    r9, rINST, #8, #4           @ r9<- A
6432    GET_VREG(r0, r2)                    @ r0<- vB
6433    .if 0
6434    cmp     r1, #0                      @ is second operand zero?
6435    beq     common_errDivideByZero
6436    .endif
6437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6438
6439    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6441    SET_VREG(r0, r9)               @ vAA<- r0
6442    GOTO_OPCODE(ip)                     @ jump to next instruction
6443    /* 10-13 instructions */
6444
6445
6446/* ------------------------------ */
6447    .balign 64
6448.L_OP_DIV_INT_LIT16: /* 0xd3 */
6449/* File: armv6t2/OP_DIV_INT_LIT16.S */
6450/* File: armv6t2/binopLit16.S */
6451    /*
6452     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6453     * that specifies an instruction that performs "result = r0 op r1".
6454     * This could be an ARM instruction or a function call.  (If the result
6455     * comes back in a register other than r0, you can override "result".)
6456     *
6457     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6458     * vCC (r1).  Useful for integer division and modulus.
6459     *
6460     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6461     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6462     */
6463    /* binop/lit16 vA, vB, #+CCCC */
6464    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6465    mov     r2, rINST, lsr #12          @ r2<- B
6466    ubfx    r9, rINST, #8, #4           @ r9<- A
6467    GET_VREG(r0, r2)                    @ r0<- vB
6468    .if 1
6469    cmp     r1, #0                      @ is second operand zero?
6470    beq     common_errDivideByZero
6471    .endif
6472    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6473
6474    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6475    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6476    SET_VREG(r0, r9)               @ vAA<- r0
6477    GOTO_OPCODE(ip)                     @ jump to next instruction
6478    /* 10-13 instructions */
6479
6480
6481/* ------------------------------ */
6482    .balign 64
6483.L_OP_REM_INT_LIT16: /* 0xd4 */
6484/* File: armv6t2/OP_REM_INT_LIT16.S */
6485/* idivmod returns quotient in r0 and remainder in r1 */
6486/* File: armv6t2/binopLit16.S */
6487    /*
6488     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6489     * that specifies an instruction that performs "result = r0 op r1".
6490     * This could be an ARM instruction or a function call.  (If the result
6491     * comes back in a register other than r0, you can override "result".)
6492     *
6493     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6494     * vCC (r1).  Useful for integer division and modulus.
6495     *
6496     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6497     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6498     */
6499    /* binop/lit16 vA, vB, #+CCCC */
6500    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6501    mov     r2, rINST, lsr #12          @ r2<- B
6502    ubfx    r9, rINST, #8, #4           @ r9<- A
6503    GET_VREG(r0, r2)                    @ r0<- vB
6504    .if 1
6505    cmp     r1, #0                      @ is second operand zero?
6506    beq     common_errDivideByZero
6507    .endif
6508    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6509
6510    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6512    SET_VREG(r1, r9)               @ vAA<- r1
6513    GOTO_OPCODE(ip)                     @ jump to next instruction
6514    /* 10-13 instructions */
6515
6516
6517/* ------------------------------ */
6518    .balign 64
6519.L_OP_AND_INT_LIT16: /* 0xd5 */
6520/* File: armv6t2/OP_AND_INT_LIT16.S */
6521/* File: armv6t2/binopLit16.S */
6522    /*
6523     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6524     * that specifies an instruction that performs "result = r0 op r1".
6525     * This could be an ARM instruction or a function call.  (If the result
6526     * comes back in a register other than r0, you can override "result".)
6527     *
6528     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6529     * vCC (r1).  Useful for integer division and modulus.
6530     *
6531     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6532     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6533     */
6534    /* binop/lit16 vA, vB, #+CCCC */
6535    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6536    mov     r2, rINST, lsr #12          @ r2<- B
6537    ubfx    r9, rINST, #8, #4           @ r9<- A
6538    GET_VREG(r0, r2)                    @ r0<- vB
6539    .if 0
6540    cmp     r1, #0                      @ is second operand zero?
6541    beq     common_errDivideByZero
6542    .endif
6543    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6544
6545    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6546    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6547    SET_VREG(r0, r9)               @ vAA<- r0
6548    GOTO_OPCODE(ip)                     @ jump to next instruction
6549    /* 10-13 instructions */
6550
6551
6552/* ------------------------------ */
6553    .balign 64
6554.L_OP_OR_INT_LIT16: /* 0xd6 */
6555/* File: armv6t2/OP_OR_INT_LIT16.S */
6556/* File: armv6t2/binopLit16.S */
6557    /*
6558     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6559     * that specifies an instruction that performs "result = r0 op r1".
6560     * This could be an ARM instruction or a function call.  (If the result
6561     * comes back in a register other than r0, you can override "result".)
6562     *
6563     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6564     * vCC (r1).  Useful for integer division and modulus.
6565     *
6566     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6567     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6568     */
6569    /* binop/lit16 vA, vB, #+CCCC */
6570    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6571    mov     r2, rINST, lsr #12          @ r2<- B
6572    ubfx    r9, rINST, #8, #4           @ r9<- A
6573    GET_VREG(r0, r2)                    @ r0<- vB
6574    .if 0
6575    cmp     r1, #0                      @ is second operand zero?
6576    beq     common_errDivideByZero
6577    .endif
6578    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6579
6580    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6581    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6582    SET_VREG(r0, r9)               @ vAA<- r0
6583    GOTO_OPCODE(ip)                     @ jump to next instruction
6584    /* 10-13 instructions */
6585
6586
6587/* ------------------------------ */
6588    .balign 64
6589.L_OP_XOR_INT_LIT16: /* 0xd7 */
6590/* File: armv6t2/OP_XOR_INT_LIT16.S */
6591/* File: armv6t2/binopLit16.S */
6592    /*
6593     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6594     * that specifies an instruction that performs "result = r0 op r1".
6595     * This could be an ARM instruction or a function call.  (If the result
6596     * comes back in a register other than r0, you can override "result".)
6597     *
6598     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6599     * vCC (r1).  Useful for integer division and modulus.
6600     *
6601     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6602     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6603     */
6604    /* binop/lit16 vA, vB, #+CCCC */
6605    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6606    mov     r2, rINST, lsr #12          @ r2<- B
6607    ubfx    r9, rINST, #8, #4           @ r9<- A
6608    GET_VREG(r0, r2)                    @ r0<- vB
6609    .if 0
6610    cmp     r1, #0                      @ is second operand zero?
6611    beq     common_errDivideByZero
6612    .endif
6613    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6614
6615    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6616    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6617    SET_VREG(r0, r9)               @ vAA<- r0
6618    GOTO_OPCODE(ip)                     @ jump to next instruction
6619    /* 10-13 instructions */
6620
6621
6622/* ------------------------------ */
6623    .balign 64
6624.L_OP_ADD_INT_LIT8: /* 0xd8 */
6625/* File: armv5te/OP_ADD_INT_LIT8.S */
6626/* File: armv5te/binopLit8.S */
6627    /*
6628     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6629     * that specifies an instruction that performs "result = r0 op r1".
6630     * This could be an ARM instruction or a function call.  (If the result
6631     * comes back in a register other than r0, you can override "result".)
6632     *
6633     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6634     * vCC (r1).  Useful for integer division and modulus.
6635     *
6636     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6637     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6638     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6639     */
6640    /* binop/lit8 vAA, vBB, #+CC */
6641    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6642    mov     r9, rINST, lsr #8           @ r9<- AA
6643    and     r2, r3, #255                @ r2<- BB
6644    GET_VREG(r0, r2)                    @ r0<- vBB
6645    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6646    .if 0
6647    @cmp     r1, #0                      @ is second operand zero?
6648    beq     common_errDivideByZero
6649    .endif
6650    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6651
6652                               @ optional op; may set condition codes
6653    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6654    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6655    SET_VREG(r0, r9)               @ vAA<- r0
6656    GOTO_OPCODE(ip)                     @ jump to next instruction
6657    /* 10-12 instructions */
6658
6659
6660/* ------------------------------ */
6661    .balign 64
6662.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6663/* File: armv5te/OP_RSUB_INT_LIT8.S */
6664/* File: armv5te/binopLit8.S */
6665    /*
6666     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6667     * that specifies an instruction that performs "result = r0 op r1".
6668     * This could be an ARM instruction or a function call.  (If the result
6669     * comes back in a register other than r0, you can override "result".)
6670     *
6671     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6672     * vCC (r1).  Useful for integer division and modulus.
6673     *
6674     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6675     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6676     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6677     */
6678    /* binop/lit8 vAA, vBB, #+CC */
6679    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6680    mov     r9, rINST, lsr #8           @ r9<- AA
6681    and     r2, r3, #255                @ r2<- BB
6682    GET_VREG(r0, r2)                    @ r0<- vBB
6683    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6684    .if 0
6685    @cmp     r1, #0                      @ is second operand zero?
6686    beq     common_errDivideByZero
6687    .endif
6688    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6689
6690                               @ optional op; may set condition codes
6691    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6692    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6693    SET_VREG(r0, r9)               @ vAA<- r0
6694    GOTO_OPCODE(ip)                     @ jump to next instruction
6695    /* 10-12 instructions */
6696
6697
6698/* ------------------------------ */
6699    .balign 64
6700.L_OP_MUL_INT_LIT8: /* 0xda */
6701/* File: armv5te/OP_MUL_INT_LIT8.S */
6702/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6703/* File: armv5te/binopLit8.S */
6704    /*
6705     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6706     * that specifies an instruction that performs "result = r0 op r1".
6707     * This could be an ARM instruction or a function call.  (If the result
6708     * comes back in a register other than r0, you can override "result".)
6709     *
6710     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6711     * vCC (r1).  Useful for integer division and modulus.
6712     *
6713     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6714     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6715     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6716     */
6717    /* binop/lit8 vAA, vBB, #+CC */
6718    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6719    mov     r9, rINST, lsr #8           @ r9<- AA
6720    and     r2, r3, #255                @ r2<- BB
6721    GET_VREG(r0, r2)                    @ r0<- vBB
6722    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6723    .if 0
6724    @cmp     r1, #0                      @ is second operand zero?
6725    beq     common_errDivideByZero
6726    .endif
6727    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6728
6729                               @ optional op; may set condition codes
6730    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6731    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6732    SET_VREG(r0, r9)               @ vAA<- r0
6733    GOTO_OPCODE(ip)                     @ jump to next instruction
6734    /* 10-12 instructions */
6735
6736
6737/* ------------------------------ */
6738    .balign 64
6739.L_OP_DIV_INT_LIT8: /* 0xdb */
6740/* File: armv5te/OP_DIV_INT_LIT8.S */
6741/* File: armv5te/binopLit8.S */
6742    /*
6743     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6744     * that specifies an instruction that performs "result = r0 op r1".
6745     * This could be an ARM instruction or a function call.  (If the result
6746     * comes back in a register other than r0, you can override "result".)
6747     *
6748     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6749     * vCC (r1).  Useful for integer division and modulus.
6750     *
6751     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6752     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6753     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6754     */
6755    /* binop/lit8 vAA, vBB, #+CC */
6756    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6757    mov     r9, rINST, lsr #8           @ r9<- AA
6758    and     r2, r3, #255                @ r2<- BB
6759    GET_VREG(r0, r2)                    @ r0<- vBB
6760    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6761    .if 1
6762    @cmp     r1, #0                      @ is second operand zero?
6763    beq     common_errDivideByZero
6764    .endif
6765    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6766
6767                               @ optional op; may set condition codes
6768    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6769    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6770    SET_VREG(r0, r9)               @ vAA<- r0
6771    GOTO_OPCODE(ip)                     @ jump to next instruction
6772    /* 10-12 instructions */
6773
6774
6775/* ------------------------------ */
6776    .balign 64
6777.L_OP_REM_INT_LIT8: /* 0xdc */
6778/* File: armv5te/OP_REM_INT_LIT8.S */
6779/* idivmod returns quotient in r0 and remainder in r1 */
6780/* File: armv5te/binopLit8.S */
6781    /*
6782     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6783     * that specifies an instruction that performs "result = r0 op r1".
6784     * This could be an ARM instruction or a function call.  (If the result
6785     * comes back in a register other than r0, you can override "result".)
6786     *
6787     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6788     * vCC (r1).  Useful for integer division and modulus.
6789     *
6790     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6791     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6792     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6793     */
6794    /* binop/lit8 vAA, vBB, #+CC */
6795    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6796    mov     r9, rINST, lsr #8           @ r9<- AA
6797    and     r2, r3, #255                @ r2<- BB
6798    GET_VREG(r0, r2)                    @ r0<- vBB
6799    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6800    .if 1
6801    @cmp     r1, #0                      @ is second operand zero?
6802    beq     common_errDivideByZero
6803    .endif
6804    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6805
6806                               @ optional op; may set condition codes
6807    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6808    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6809    SET_VREG(r1, r9)               @ vAA<- r1
6810    GOTO_OPCODE(ip)                     @ jump to next instruction
6811    /* 10-12 instructions */
6812
6813
6814/* ------------------------------ */
6815    .balign 64
6816.L_OP_AND_INT_LIT8: /* 0xdd */
6817/* File: armv5te/OP_AND_INT_LIT8.S */
6818/* File: armv5te/binopLit8.S */
6819    /*
6820     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6821     * that specifies an instruction that performs "result = r0 op r1".
6822     * This could be an ARM instruction or a function call.  (If the result
6823     * comes back in a register other than r0, you can override "result".)
6824     *
6825     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6826     * vCC (r1).  Useful for integer division and modulus.
6827     *
6828     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6829     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6830     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6831     */
6832    /* binop/lit8 vAA, vBB, #+CC */
6833    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6834    mov     r9, rINST, lsr #8           @ r9<- AA
6835    and     r2, r3, #255                @ r2<- BB
6836    GET_VREG(r0, r2)                    @ r0<- vBB
6837    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6838    .if 0
6839    @cmp     r1, #0                      @ is second operand zero?
6840    beq     common_errDivideByZero
6841    .endif
6842    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6843
6844                               @ optional op; may set condition codes
6845    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6846    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6847    SET_VREG(r0, r9)               @ vAA<- r0
6848    GOTO_OPCODE(ip)                     @ jump to next instruction
6849    /* 10-12 instructions */
6850
6851
6852/* ------------------------------ */
6853    .balign 64
6854.L_OP_OR_INT_LIT8: /* 0xde */
6855/* File: armv5te/OP_OR_INT_LIT8.S */
6856/* File: armv5te/binopLit8.S */
6857    /*
6858     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6859     * that specifies an instruction that performs "result = r0 op r1".
6860     * This could be an ARM instruction or a function call.  (If the result
6861     * comes back in a register other than r0, you can override "result".)
6862     *
6863     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6864     * vCC (r1).  Useful for integer division and modulus.
6865     *
6866     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6867     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6868     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6869     */
6870    /* binop/lit8 vAA, vBB, #+CC */
6871    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6872    mov     r9, rINST, lsr #8           @ r9<- AA
6873    and     r2, r3, #255                @ r2<- BB
6874    GET_VREG(r0, r2)                    @ r0<- vBB
6875    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6876    .if 0
6877    @cmp     r1, #0                      @ is second operand zero?
6878    beq     common_errDivideByZero
6879    .endif
6880    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6881
6882                               @ optional op; may set condition codes
6883    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6885    SET_VREG(r0, r9)               @ vAA<- r0
6886    GOTO_OPCODE(ip)                     @ jump to next instruction
6887    /* 10-12 instructions */
6888
6889
6890/* ------------------------------ */
6891    .balign 64
6892.L_OP_XOR_INT_LIT8: /* 0xdf */
6893/* File: armv5te/OP_XOR_INT_LIT8.S */
6894/* File: armv5te/binopLit8.S */
6895    /*
6896     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6897     * that specifies an instruction that performs "result = r0 op r1".
6898     * This could be an ARM instruction or a function call.  (If the result
6899     * comes back in a register other than r0, you can override "result".)
6900     *
6901     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6902     * vCC (r1).  Useful for integer division and modulus.
6903     *
6904     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6905     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6906     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6907     */
6908    /* binop/lit8 vAA, vBB, #+CC */
6909    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6910    mov     r9, rINST, lsr #8           @ r9<- AA
6911    and     r2, r3, #255                @ r2<- BB
6912    GET_VREG(r0, r2)                    @ r0<- vBB
6913    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6914    .if 0
6915    @cmp     r1, #0                      @ is second operand zero?
6916    beq     common_errDivideByZero
6917    .endif
6918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6919
6920                               @ optional op; may set condition codes
6921    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6922    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6923    SET_VREG(r0, r9)               @ vAA<- r0
6924    GOTO_OPCODE(ip)                     @ jump to next instruction
6925    /* 10-12 instructions */
6926
6927
6928/* ------------------------------ */
6929    .balign 64
6930.L_OP_SHL_INT_LIT8: /* 0xe0 */
6931/* File: armv5te/OP_SHL_INT_LIT8.S */
6932/* File: armv5te/binopLit8.S */
6933    /*
6934     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6935     * that specifies an instruction that performs "result = r0 op r1".
6936     * This could be an ARM instruction or a function call.  (If the result
6937     * comes back in a register other than r0, you can override "result".)
6938     *
6939     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6940     * vCC (r1).  Useful for integer division and modulus.
6941     *
6942     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6943     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6944     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6945     */
6946    /* binop/lit8 vAA, vBB, #+CC */
6947    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6948    mov     r9, rINST, lsr #8           @ r9<- AA
6949    and     r2, r3, #255                @ r2<- BB
6950    GET_VREG(r0, r2)                    @ r0<- vBB
6951    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6952    .if 0
6953    @cmp     r1, #0                      @ is second operand zero?
6954    beq     common_errDivideByZero
6955    .endif
6956    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6957
6958    and     r1, r1, #31                           @ optional op; may set condition codes
6959    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
6960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6961    SET_VREG(r0, r9)               @ vAA<- r0
6962    GOTO_OPCODE(ip)                     @ jump to next instruction
6963    /* 10-12 instructions */
6964
6965
6966/* ------------------------------ */
6967    .balign 64
6968.L_OP_SHR_INT_LIT8: /* 0xe1 */
6969/* File: armv5te/OP_SHR_INT_LIT8.S */
6970/* File: armv5te/binopLit8.S */
6971    /*
6972     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6973     * that specifies an instruction that performs "result = r0 op r1".
6974     * This could be an ARM instruction or a function call.  (If the result
6975     * comes back in a register other than r0, you can override "result".)
6976     *
6977     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6978     * vCC (r1).  Useful for integer division and modulus.
6979     *
6980     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6981     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6982     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6983     */
6984    /* binop/lit8 vAA, vBB, #+CC */
6985    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6986    mov     r9, rINST, lsr #8           @ r9<- AA
6987    and     r2, r3, #255                @ r2<- BB
6988    GET_VREG(r0, r2)                    @ r0<- vBB
6989    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6990    .if 0
6991    @cmp     r1, #0                      @ is second operand zero?
6992    beq     common_errDivideByZero
6993    .endif
6994    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6995
6996    and     r1, r1, #31                           @ optional op; may set condition codes
6997    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
6998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6999    SET_VREG(r0, r9)               @ vAA<- r0
7000    GOTO_OPCODE(ip)                     @ jump to next instruction
7001    /* 10-12 instructions */
7002
7003
7004/* ------------------------------ */
7005    .balign 64
7006.L_OP_USHR_INT_LIT8: /* 0xe2 */
7007/* File: armv5te/OP_USHR_INT_LIT8.S */
7008/* File: armv5te/binopLit8.S */
7009    /*
7010     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7011     * that specifies an instruction that performs "result = r0 op r1".
7012     * This could be an ARM instruction or a function call.  (If the result
7013     * comes back in a register other than r0, you can override "result".)
7014     *
7015     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7016     * vCC (r1).  Useful for integer division and modulus.
7017     *
7018     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7019     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7020     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7021     */
7022    /* binop/lit8 vAA, vBB, #+CC */
7023    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7024    mov     r9, rINST, lsr #8           @ r9<- AA
7025    and     r2, r3, #255                @ r2<- BB
7026    GET_VREG(r0, r2)                    @ r0<- vBB
7027    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7028    .if 0
7029    @cmp     r1, #0                      @ is second operand zero?
7030    beq     common_errDivideByZero
7031    .endif
7032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7033
7034    and     r1, r1, #31                           @ optional op; may set condition codes
7035    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7037    SET_VREG(r0, r9)               @ vAA<- r0
7038    GOTO_OPCODE(ip)                     @ jump to next instruction
7039    /* 10-12 instructions */
7040
7041
7042/* ------------------------------ */
7043    .balign 64
7044.L_OP_IGET_VOLATILE: /* 0xe3 */
7045/* File: armv5te/OP_IGET_VOLATILE.S */
7046/* File: armv5te/OP_IGET.S */
7047    /*
7048     * General 32-bit instance field get.
7049     *
7050     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7051     */
7052    /* op vA, vB, field@CCCC */
7053    mov     r0, rINST, lsr #12          @ r0<- B
7054    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7055    FETCH(r1, 1)                        @ r1<- field ref CCCC
7056    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7057    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7058    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7059    cmp     r0, #0                      @ is resolved entry null?
7060    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
70618:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7062    EXPORT_PC()                         @ resolve() could throw
7063    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7064    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7065    cmp     r0, #0
7066    bne     .LOP_IGET_VOLATILE_finish
7067    b       common_exceptionThrown
7068
7069
7070/* ------------------------------ */
7071    .balign 64
7072.L_OP_IPUT_VOLATILE: /* 0xe4 */
7073/* File: armv5te/OP_IPUT_VOLATILE.S */
7074/* File: armv5te/OP_IPUT.S */
7075    /*
7076     * General 32-bit instance field put.
7077     *
7078     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7079     */
7080    /* op vA, vB, field@CCCC */
7081    mov     r0, rINST, lsr #12          @ r0<- B
7082    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7083    FETCH(r1, 1)                        @ r1<- field ref CCCC
7084    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7085    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7086    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7087    cmp     r0, #0                      @ is resolved entry null?
7088    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
70898:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7090    EXPORT_PC()                         @ resolve() could throw
7091    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7092    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7093    cmp     r0, #0                      @ success?
7094    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7095    b       common_exceptionThrown
7096
7097
7098/* ------------------------------ */
7099    .balign 64
7100.L_OP_SGET_VOLATILE: /* 0xe5 */
7101/* File: armv5te/OP_SGET_VOLATILE.S */
7102/* File: armv5te/OP_SGET.S */
7103    /*
7104     * General 32-bit SGET handler.
7105     *
7106     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7107     */
7108    /* op vAA, field@BBBB */
7109    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7110    FETCH(r1, 1)                        @ r1<- field ref BBBB
7111    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7112    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7113    cmp     r0, #0                      @ is resolved entry null?
7114    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7115.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7116    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7117    SMP_DMB                            @ acquiring load
7118    mov     r2, rINST, lsr #8           @ r2<- AA
7119    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7120    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7122    GOTO_OPCODE(ip)                     @ jump to next instruction
7123
7124
7125/* ------------------------------ */
7126    .balign 64
7127.L_OP_SPUT_VOLATILE: /* 0xe6 */
7128/* File: armv5te/OP_SPUT_VOLATILE.S */
7129/* File: armv5te/OP_SPUT.S */
7130    /*
7131     * General 32-bit SPUT handler.
7132     *
7133     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7134     */
7135    /* op vAA, field@BBBB */
7136    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7137    FETCH(r1, 1)                        @ r1<- field ref BBBB
7138    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7139    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7140    cmp     r0, #0                      @ is resolved entry null?
7141    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7142.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7143    mov     r2, rINST, lsr #8           @ r2<- AA
7144    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7145    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7147    SMP_DMB                            @ releasing store
7148    str     r1, [r0, #offStaticField_value] @ field<- vAA
7149    GOTO_OPCODE(ip)                     @ jump to next instruction
7150
7151
7152/* ------------------------------ */
7153    .balign 64
7154.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7155/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7156/* File: armv5te/OP_IGET.S */
7157    /*
7158     * General 32-bit instance field get.
7159     *
7160     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7161     */
7162    /* op vA, vB, field@CCCC */
7163    mov     r0, rINST, lsr #12          @ r0<- B
7164    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7165    FETCH(r1, 1)                        @ r1<- field ref CCCC
7166    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7167    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7168    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7169    cmp     r0, #0                      @ is resolved entry null?
7170    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
71718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7172    EXPORT_PC()                         @ resolve() could throw
7173    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7174    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7175    cmp     r0, #0
7176    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7177    b       common_exceptionThrown
7178
7179
7180/* ------------------------------ */
7181    .balign 64
7182.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7183/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7184/* File: armv5te/OP_IGET_WIDE.S */
7185    /*
7186     * Wide 32-bit instance field get.
7187     */
7188    /* iget-wide vA, vB, field@CCCC */
7189    mov     r0, rINST, lsr #12          @ r0<- B
7190    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7191    FETCH(r1, 1)                        @ r1<- field ref CCCC
7192    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7193    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7194    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7195    cmp     r0, #0                      @ is resolved entry null?
7196    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
71978:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7198    EXPORT_PC()                         @ resolve() could throw
7199    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7200    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7201    cmp     r0, #0
7202    bne     .LOP_IGET_WIDE_VOLATILE_finish
7203    b       common_exceptionThrown
7204
7205
7206/* ------------------------------ */
7207    .balign 64
7208.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7209/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7210/* File: armv5te/OP_IPUT_WIDE.S */
7211    /* iput-wide vA, vB, field@CCCC */
7212    mov     r0, rINST, lsr #12          @ r0<- B
7213    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7214    FETCH(r1, 1)                        @ r1<- field ref CCCC
7215    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7216    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7217    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7218    cmp     r0, #0                      @ is resolved entry null?
7219    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72208:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7221    EXPORT_PC()                         @ resolve() could throw
7222    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7223    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7224    cmp     r0, #0                      @ success?
7225    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7226    b       common_exceptionThrown
7227
7228
7229/* ------------------------------ */
7230    .balign 64
7231.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7232/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7233/* File: armv5te/OP_SGET_WIDE.S */
7234    /*
7235     * 64-bit SGET handler.
7236     */
7237    /* sget-wide vAA, field@BBBB */
7238    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7239    FETCH(r1, 1)                        @ r1<- field ref BBBB
7240    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7241    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7242    cmp     r0, #0                      @ is resolved entry null?
7243    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7244.LOP_SGET_WIDE_VOLATILE_finish:
7245    mov     r9, rINST, lsr #8           @ r9<- AA
7246    .if 1
7247    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7248    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7249    .else
7250    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7251    .endif
7252    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7254    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7256    GOTO_OPCODE(ip)                     @ jump to next instruction
7257
7258
7259/* ------------------------------ */
7260    .balign 64
7261.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7262/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7263/* File: armv5te/OP_SPUT_WIDE.S */
7264    /*
7265     * 64-bit SPUT handler.
7266     */
7267    /* sput-wide vAA, field@BBBB */
7268    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7269    FETCH(r1, 1)                        @ r1<- field ref BBBB
7270    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7271    mov     r9, rINST, lsr #8           @ r9<- AA
7272    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7273    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7274    cmp     r2, #0                      @ is resolved entry null?
7275    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7276.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7278    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7279    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7280    .if 1
7281    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7282    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7283    .else
7284    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7285    .endif
7286    GOTO_OPCODE(r10)                    @ jump to next instruction
7287
7288
7289/* ------------------------------ */
7290    .balign 64
7291.L_OP_BREAKPOINT: /* 0xec */
7292/* File: armv5te/OP_BREAKPOINT.S */
7293/* File: armv5te/unused.S */
7294    bl      common_abort
7295
7296
7297/* ------------------------------ */
7298    .balign 64
7299.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7300/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7301    /*
7302     * Handle a throw-verification-error instruction.  This throws an
7303     * exception for an error discovered during verification.  The
7304     * exception is indicated by AA, with some detail provided by BBBB.
7305     */
7306    /* op AA, ref@BBBB */
7307    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7308    FETCH(r2, 1)                        @ r2<- BBBB
7309    EXPORT_PC()                         @ export the PC
7310    mov     r1, rINST, lsr #8           @ r1<- AA
7311    bl      dvmThrowVerificationError   @ always throws
7312    b       common_exceptionThrown      @ handle exception
7313
7314/* ------------------------------ */
7315    .balign 64
7316.L_OP_EXECUTE_INLINE: /* 0xee */
7317/* File: armv5te/OP_EXECUTE_INLINE.S */
7318    /*
7319     * Execute a "native inline" instruction.
7320     *
7321     * We need to call an InlineOp4Func:
7322     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7323     *
7324     * The first four args are in r0-r3, pointer to return value storage
7325     * is on the stack.  The function's return value is a flag that tells
7326     * us if an exception was thrown.
7327     */
7328    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7329    FETCH(r10, 1)                       @ r10<- BBBB
7330    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7331    EXPORT_PC()                         @ can throw
7332    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7333    mov     r0, rINST, lsr #12          @ r0<- B
7334    str     r1, [sp]                    @ push &glue->retval
7335    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7336    add     sp, sp, #8                  @ pop stack
7337    cmp     r0, #0                      @ test boolean result of inline
7338    beq     common_exceptionThrown      @ returned false, handle exception
7339    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7340    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7341    GOTO_OPCODE(ip)                     @ jump to next instruction
7342
7343/* ------------------------------ */
7344    .balign 64
7345.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7346/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7347    /*
7348     * Execute a "native inline" instruction, using "/range" semantics.
7349     * Same idea as execute-inline, but we get the args differently.
7350     *
7351     * We need to call an InlineOp4Func:
7352     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7353     *
7354     * The first four args are in r0-r3, pointer to return value storage
7355     * is on the stack.  The function's return value is a flag that tells
7356     * us if an exception was thrown.
7357     */
7358    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7359    FETCH(r10, 1)                       @ r10<- BBBB
7360    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7361    EXPORT_PC()                         @ can throw
7362    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7363    mov     r0, rINST, lsr #8           @ r0<- AA
7364    str     r1, [sp]                    @ push &glue->retval
7365    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7366    add     sp, sp, #8                  @ pop stack
7367    cmp     r0, #0                      @ test boolean result of inline
7368    beq     common_exceptionThrown      @ returned false, handle exception
7369    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7371    GOTO_OPCODE(ip)                     @ jump to next instruction
7372
7373/* ------------------------------ */
7374    .balign 64
7375.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7376/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7377    /*
7378     * invoke-direct-empty is a no-op in a "standard" interpreter.
7379     */
7380    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7381    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7382    GOTO_OPCODE(ip)                     @ execute it
7383
7384/* ------------------------------ */
7385    .balign 64
7386.L_OP_RETURN_VOID_BARRIER: /* 0xf1 */
7387/* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7388    SMP_DMB_ST
7389    b       common_returnFromMethod
7390
7391/* ------------------------------ */
7392    .balign 64
7393.L_OP_IGET_QUICK: /* 0xf2 */
7394/* File: armv6t2/OP_IGET_QUICK.S */
7395    /* For: iget-quick, iget-object-quick */
7396    /* op vA, vB, offset@CCCC */
7397    mov     r2, rINST, lsr #12          @ r2<- B
7398    FETCH(r1, 1)                        @ r1<- field byte offset
7399    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7400    ubfx    r2, rINST, #8, #4           @ r2<- A
7401    cmp     r3, #0                      @ check object for null
7402    beq     common_errNullObject        @ object was null
7403    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7404    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7406    SET_VREG(r0, r2)                    @ fp[A]<- r0
7407    GOTO_OPCODE(ip)                     @ jump to next instruction
7408
7409/* ------------------------------ */
7410    .balign 64
7411.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7412/* File: armv6t2/OP_IGET_WIDE_QUICK.S */
7413    /* iget-wide-quick vA, vB, offset@CCCC */
7414    mov     r2, rINST, lsr #12          @ r2<- B
7415    FETCH(ip, 1)                        @ ip<- field byte offset
7416    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7417    ubfx    r2, rINST, #8, #4           @ r2<- A
7418    cmp     r3, #0                      @ check object for null
7419    beq     common_errNullObject        @ object was null
7420    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7421    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7422    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7423    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7424    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7425    GOTO_OPCODE(ip)                     @ jump to next instruction
7426
7427/* ------------------------------ */
7428    .balign 64
7429.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7430/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7431/* File: armv5te/OP_IGET_QUICK.S */
7432    /* For: iget-quick, iget-object-quick */
7433    /* op vA, vB, offset@CCCC */
7434    mov     r2, rINST, lsr #12          @ r2<- B
7435    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7436    FETCH(r1, 1)                        @ r1<- field byte offset
7437    cmp     r3, #0                      @ check object for null
7438    mov     r2, rINST, lsr #8           @ r2<- A(+)
7439    beq     common_errNullObject        @ object was null
7440    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7441    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7442    and     r2, r2, #15
7443    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7444    SET_VREG(r0, r2)                    @ fp[A]<- r0
7445    GOTO_OPCODE(ip)                     @ jump to next instruction
7446
7447
7448/* ------------------------------ */
7449    .balign 64
7450.L_OP_IPUT_QUICK: /* 0xf5 */
7451/* File: armv6t2/OP_IPUT_QUICK.S */
7452    /* For: iput-quick, iput-object-quick */
7453    /* op vA, vB, offset@CCCC */
7454    mov     r2, rINST, lsr #12          @ r2<- B
7455    FETCH(r1, 1)                        @ r1<- field byte offset
7456    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7457    ubfx    r2, rINST, #8, #4           @ r2<- A
7458    cmp     r3, #0                      @ check object for null
7459    beq     common_errNullObject        @ object was null
7460    GET_VREG(r0, r2)                    @ r0<- fp[A]
7461    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7462    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7463    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7464    GOTO_OPCODE(ip)                     @ jump to next instruction
7465
7466/* ------------------------------ */
7467    .balign 64
7468.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7469/* File: armv6t2/OP_IPUT_WIDE_QUICK.S */
7470    /* iput-wide-quick vA, vB, offset@CCCC */
7471    mov     r1, rINST, lsr #12          @ r1<- B
7472    ubfx    r0, rINST, #8, #4           @ r0<- A
7473    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7474    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7475    cmp     r2, #0                      @ check object for null
7476    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7477    beq     common_errNullObject        @ object was null
7478    FETCH(r3, 1)                        @ r3<- field byte offset
7479    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7480    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7481    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7482    GOTO_OPCODE(ip)                     @ jump to next instruction
7483
7484/* ------------------------------ */
7485    .balign 64
7486.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7487/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7488    /* For: iput-object-quick */
7489    /* op vA, vB, offset@CCCC */
7490    mov     r2, rINST, lsr #12          @ r2<- B
7491    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7492    FETCH(r1, 1)                        @ r1<- field byte offset
7493    cmp     r3, #0                      @ check object for null
7494    mov     r2, rINST, lsr #8           @ r2<- A(+)
7495    beq     common_errNullObject        @ object was null
7496    and     r2, r2, #15
7497    GET_VREG(r0, r2)                    @ r0<- fp[A]
7498    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7499    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7500    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7501    cmp     r0, #0
7502    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7504    GOTO_OPCODE(ip)                     @ jump to next instruction
7505
7506/* ------------------------------ */
7507    .balign 64
7508.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7509/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7510    /*
7511     * Handle an optimized virtual method call.
7512     *
7513     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7514     */
7515    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7516    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7517    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7518    FETCH(r1, 1)                        @ r1<- BBBB
7519    .if     (!0)
7520    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7521    .endif
7522    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7523    cmp     r2, #0                      @ is "this" null?
7524    beq     common_errNullObject        @ null "this", throw exception
7525    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7526    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7527    EXPORT_PC()                         @ invoke must export
7528    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7529    bl      common_invokeMethodNoRange @ continue on
7530
7531/* ------------------------------ */
7532    .balign 64
7533.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7534/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7535/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7536    /*
7537     * Handle an optimized virtual method call.
7538     *
7539     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7540     */
7541    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7542    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7543    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7544    FETCH(r1, 1)                        @ r1<- BBBB
7545    .if     (!1)
7546    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7547    .endif
7548    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7549    cmp     r2, #0                      @ is "this" null?
7550    beq     common_errNullObject        @ null "this", throw exception
7551    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7552    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7553    EXPORT_PC()                         @ invoke must export
7554    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7555    bl      common_invokeMethodRange @ continue on
7556
7557
7558/* ------------------------------ */
7559    .balign 64
7560.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7561/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7562    /*
7563     * Handle an optimized "super" method call.
7564     *
7565     * for: [opt] invoke-super-quick, invoke-super-quick/range
7566     */
7567    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7568    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7569    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7570    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7571    .if     (!0)
7572    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7573    .endif
7574    FETCH(r1, 1)                        @ r1<- BBBB
7575    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7576    EXPORT_PC()                         @ must export for invoke
7577    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7578    GET_VREG(r3, r10)                   @ r3<- "this"
7579    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7580    cmp     r3, #0                      @ null "this" ref?
7581    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7582    beq     common_errNullObject        @ "this" is null, throw exception
7583    bl      common_invokeMethodNoRange @ continue on
7584
7585/* ------------------------------ */
7586    .balign 64
7587.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7588/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7589/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7590    /*
7591     * Handle an optimized "super" method call.
7592     *
7593     * for: [opt] invoke-super-quick, invoke-super-quick/range
7594     */
7595    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7596    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7597    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7598    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7599    .if     (!1)
7600    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7601    .endif
7602    FETCH(r1, 1)                        @ r1<- BBBB
7603    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7604    EXPORT_PC()                         @ must export for invoke
7605    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7606    GET_VREG(r3, r10)                   @ r3<- "this"
7607    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7608    cmp     r3, #0                      @ null "this" ref?
7609    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7610    beq     common_errNullObject        @ "this" is null, throw exception
7611    bl      common_invokeMethodRange @ continue on
7612
7613
7614/* ------------------------------ */
7615    .balign 64
7616.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7617/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7618/* File: armv5te/OP_IPUT_OBJECT.S */
7619    /*
7620     * 32-bit instance field put.
7621     *
7622     * for: iput-object, iput-object-volatile
7623     */
7624    /* op vA, vB, field@CCCC */
7625    mov     r0, rINST, lsr #12          @ r0<- B
7626    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7627    FETCH(r1, 1)                        @ r1<- field ref CCCC
7628    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7629    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7630    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7631    cmp     r0, #0                      @ is resolved entry null?
7632    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76338:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7634    EXPORT_PC()                         @ resolve() could throw
7635    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7636    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7637    cmp     r0, #0                      @ success?
7638    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7639    b       common_exceptionThrown
7640
7641
7642/* ------------------------------ */
7643    .balign 64
7644.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7645/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7646/* File: armv5te/OP_SGET.S */
7647    /*
7648     * General 32-bit SGET handler.
7649     *
7650     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7651     */
7652    /* op vAA, field@BBBB */
7653    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7654    FETCH(r1, 1)                        @ r1<- field ref BBBB
7655    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7656    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7657    cmp     r0, #0                      @ is resolved entry null?
7658    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7659.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7660    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7661    SMP_DMB                            @ acquiring load
7662    mov     r2, rINST, lsr #8           @ r2<- AA
7663    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7664    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7665    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7666    GOTO_OPCODE(ip)                     @ jump to next instruction
7667
7668
7669/* ------------------------------ */
7670    .balign 64
7671.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7672/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7673/* File: armv5te/OP_SPUT_OBJECT.S */
7674    /*
7675     * 32-bit SPUT handler for objects
7676     *
7677     * for: sput-object, sput-object-volatile
7678     */
7679    /* op vAA, field@BBBB */
7680    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7681    FETCH(r1, 1)                        @ r1<- field ref BBBB
7682    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7683    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7684    cmp     r0, #0                      @ is resolved entry null?
7685    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7686    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7687    EXPORT_PC()                         @ resolve() could throw, so export now
7688    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7689    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7690    cmp     r0, #0                      @ success?
7691    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7692    b       common_exceptionThrown      @ no, handle exception
7693
7694
7695
7696/* ------------------------------ */
7697    .balign 64
7698.L_OP_UNUSED_FF: /* 0xff */
7699/* File: armv5te/OP_UNUSED_FF.S */
7700/* File: armv5te/unused.S */
7701    bl      common_abort
7702
7703
7704
7705    .balign 64
7706    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7707    .global dvmAsmInstructionEnd
7708dvmAsmInstructionEnd:
7709
7710/*
7711 * ===========================================================================
7712 *  Sister implementations
7713 * ===========================================================================
7714 */
7715    .global dvmAsmSisterStart
7716    .type   dvmAsmSisterStart, %function
7717    .text
7718    .balign 4
7719dvmAsmSisterStart:
7720
7721/* continuation for OP_CONST_STRING */
7722
7723    /*
7724     * Continuation if the String has not yet been resolved.
7725     *  r1: BBBB (String ref)
7726     *  r9: target register
7727     */
7728.LOP_CONST_STRING_resolve:
7729    EXPORT_PC()
7730    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7731    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7732    bl      dvmResolveString            @ r0<- String reference
7733    cmp     r0, #0                      @ failed?
7734    beq     common_exceptionThrown      @ yup, handle the exception
7735    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7736    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7737    SET_VREG(r0, r9)                    @ vAA<- r0
7738    GOTO_OPCODE(ip)                     @ jump to next instruction
7739
7740/* continuation for OP_CONST_STRING_JUMBO */
7741
7742    /*
7743     * Continuation if the String has not yet been resolved.
7744     *  r1: BBBBBBBB (String ref)
7745     *  r9: target register
7746     */
7747.LOP_CONST_STRING_JUMBO_resolve:
7748    EXPORT_PC()
7749    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7750    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7751    bl      dvmResolveString            @ r0<- String reference
7752    cmp     r0, #0                      @ failed?
7753    beq     common_exceptionThrown      @ yup, handle the exception
7754    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7755    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7756    SET_VREG(r0, r9)                    @ vAA<- r0
7757    GOTO_OPCODE(ip)                     @ jump to next instruction
7758
7759/* continuation for OP_CONST_CLASS */
7760
7761    /*
7762     * Continuation if the Class has not yet been resolved.
7763     *  r1: BBBB (Class ref)
7764     *  r9: target register
7765     */
7766.LOP_CONST_CLASS_resolve:
7767    EXPORT_PC()
7768    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7769    mov     r2, #1                      @ r2<- true
7770    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7771    bl      dvmResolveClass             @ r0<- Class reference
7772    cmp     r0, #0                      @ failed?
7773    beq     common_exceptionThrown      @ yup, handle the exception
7774    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7775    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7776    SET_VREG(r0, r9)                    @ vAA<- r0
7777    GOTO_OPCODE(ip)                     @ jump to next instruction
7778
7779/* continuation for OP_CHECK_CAST */
7780
7781    /*
7782     * Trivial test failed, need to perform full check.  This is common.
7783     *  r0 holds obj->clazz
7784     *  r1 holds class resolved from BBBB
7785     *  r9 holds object
7786     */
7787.LOP_CHECK_CAST_fullcheck:
7788    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7789    cmp     r0, #0                      @ failed?
7790    bne     .LOP_CHECK_CAST_okay            @ no, success
7791
7792    @ A cast has failed.  We need to throw a ClassCastException with the
7793    @ class of the object that failed to be cast.
7794    EXPORT_PC()                         @ about to throw
7795    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7796    ldr     r0, .LstrClassCastExceptionPtr
7797    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7798    bl      dvmThrowExceptionWithClassMessage
7799    b       common_exceptionThrown
7800
7801    /*
7802     * Resolution required.  This is the least-likely path.
7803     *
7804     *  r2 holds BBBB
7805     *  r9 holds object
7806     */
7807.LOP_CHECK_CAST_resolve:
7808    EXPORT_PC()                         @ resolve() could throw
7809    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7810    mov     r1, r2                      @ r1<- BBBB
7811    mov     r2, #0                      @ r2<- false
7812    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7813    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7814    cmp     r0, #0                      @ got null?
7815    beq     common_exceptionThrown      @ yes, handle exception
7816    mov     r1, r0                      @ r1<- class resolved from BBB
7817    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7818    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7819
7820.LstrClassCastExceptionPtr:
7821    .word   .LstrClassCastException
7822
7823/* continuation for OP_INSTANCE_OF */
7824
7825    /*
7826     * Trivial test failed, need to perform full check.  This is common.
7827     *  r0 holds obj->clazz
7828     *  r1 holds class resolved from BBBB
7829     *  r9 holds A
7830     */
7831.LOP_INSTANCE_OF_fullcheck:
7832    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7833    @ fall through to OP_INSTANCE_OF_store
7834
7835    /*
7836     * r0 holds boolean result
7837     * r9 holds A
7838     */
7839.LOP_INSTANCE_OF_store:
7840    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7841    SET_VREG(r0, r9)                    @ vA<- r0
7842    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7843    GOTO_OPCODE(ip)                     @ jump to next instruction
7844
7845    /*
7846     * Trivial test succeeded, save and bail.
7847     *  r9 holds A
7848     */
7849.LOP_INSTANCE_OF_trivial:
7850    mov     r0, #1                      @ indicate success
7851    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7852    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7853    SET_VREG(r0, r9)                    @ vA<- r0
7854    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7855    GOTO_OPCODE(ip)                     @ jump to next instruction
7856
7857    /*
7858     * Resolution required.  This is the least-likely path.
7859     *
7860     *  r3 holds BBBB
7861     *  r9 holds A
7862     */
7863.LOP_INSTANCE_OF_resolve:
7864    EXPORT_PC()                         @ resolve() could throw
7865    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7866    mov     r1, r3                      @ r1<- BBBB
7867    mov     r2, #1                      @ r2<- true
7868    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7869    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7870    cmp     r0, #0                      @ got null?
7871    beq     common_exceptionThrown      @ yes, handle exception
7872    mov     r1, r0                      @ r1<- class resolved from BBB
7873    mov     r3, rINST, lsr #12          @ r3<- B
7874    GET_VREG(r0, r3)                    @ r0<- vB (object)
7875    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7876    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7877
7878/* continuation for OP_NEW_INSTANCE */
7879
7880    .balign 32                          @ minimize cache lines
7881.LOP_NEW_INSTANCE_finish: @ r0=new object
7882    mov     r3, rINST, lsr #8           @ r3<- AA
7883    cmp     r0, #0                      @ failed?
7884    beq     common_exceptionThrown      @ yes, handle the exception
7885    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7887    SET_VREG(r0, r3)                    @ vAA<- r0
7888    GOTO_OPCODE(ip)                     @ jump to next instruction
7889
7890    /*
7891     * Class initialization required.
7892     *
7893     *  r0 holds class object
7894     */
7895.LOP_NEW_INSTANCE_needinit:
7896    mov     r9, r0                      @ save r0
7897    bl      dvmInitClass                @ initialize class
7898    cmp     r0, #0                      @ check boolean result
7899    mov     r0, r9                      @ restore r0
7900    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7901    b       common_exceptionThrown      @ failed, deal with init exception
7902
7903    /*
7904     * Resolution required.  This is the least-likely path.
7905     *
7906     *  r1 holds BBBB
7907     */
7908.LOP_NEW_INSTANCE_resolve:
7909    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7910    mov     r2, #0                      @ r2<- false
7911    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7912    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7913    cmp     r0, #0                      @ got null?
7914    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7915    b       common_exceptionThrown      @ yes, handle exception
7916
7917.LstrInstantiationErrorPtr:
7918    .word   .LstrInstantiationError
7919
7920/* continuation for OP_NEW_ARRAY */
7921
7922
7923    /*
7924     * Resolve class.  (This is an uncommon case.)
7925     *
7926     *  r1 holds array length
7927     *  r2 holds class ref CCCC
7928     */
7929.LOP_NEW_ARRAY_resolve:
7930    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7931    mov     r9, r1                      @ r9<- length (save)
7932    mov     r1, r2                      @ r1<- CCCC
7933    mov     r2, #0                      @ r2<- false
7934    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7935    bl      dvmResolveClass             @ r0<- call(clazz, ref)
7936    cmp     r0, #0                      @ got null?
7937    mov     r1, r9                      @ r1<- length (restore)
7938    beq     common_exceptionThrown      @ yes, handle exception
7939    @ fall through to OP_NEW_ARRAY_finish
7940
7941    /*
7942     * Finish allocation.
7943     *
7944     *  r0 holds class
7945     *  r1 holds array length
7946     */
7947.LOP_NEW_ARRAY_finish:
7948    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
7949    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
7950    cmp     r0, #0                      @ failed?
7951    mov     r2, rINST, lsr #8           @ r2<- A+
7952    beq     common_exceptionThrown      @ yes, handle the exception
7953    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7954    and     r2, r2, #15                 @ r2<- A
7955    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7956    SET_VREG(r0, r2)                    @ vA<- r0
7957    GOTO_OPCODE(ip)                     @ jump to next instruction
7958
7959/* continuation for OP_FILLED_NEW_ARRAY */
7960
7961    /*
7962     * On entry:
7963     *  r0 holds array class
7964     *  r10 holds AA or BA
7965     */
7966.LOP_FILLED_NEW_ARRAY_continue:
7967    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
7968    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
7969    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
7970    .if     0
7971    mov     r1, r10                     @ r1<- AA (length)
7972    .else
7973    mov     r1, r10, lsr #4             @ r1<- B (length)
7974    .endif
7975    cmp     rINST, #'I'                 @ array of ints?
7976    cmpne   rINST, #'L'                 @ array of objects?
7977    cmpne   rINST, #'['                 @ array of arrays?
7978    mov     r9, r1                      @ save length in r9
7979    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
7980    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
7981    cmp     r0, #0                      @ null return?
7982    beq     common_exceptionThrown      @ alloc failed, handle exception
7983
7984    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
7985    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
7986    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
7987    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
7988    subs    r9, r9, #1                  @ length--, check for neg
7989    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7990    bmi     2f                          @ was zero, bail
7991
7992    @ copy values from registers into the array
7993    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
7994    .if     0
7995    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
79961:  ldr     r3, [r2], #4                @ r3<- *r2++
7997    subs    r9, r9, #1                  @ count--
7998    str     r3, [r0], #4                @ *contents++ = vX
7999    bpl     1b
8000    @ continue at 2
8001    .else
8002    cmp     r9, #4                      @ length was initially 5?
8003    and     r2, r10, #15                @ r2<- A
8004    bne     1f                          @ <= 4 args, branch
8005    GET_VREG(r3, r2)                    @ r3<- vA
8006    sub     r9, r9, #1                  @ count--
8007    str     r3, [r0, #16]               @ contents[4] = vA
80081:  and     r2, r1, #15                 @ r2<- F/E/D/C
8009    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8010    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8011    subs    r9, r9, #1                  @ count--
8012    str     r3, [r0], #4                @ *contents++ = vX
8013    bpl     1b
8014    @ continue at 2
8015    .endif
8016
80172:
8018    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8019    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8020    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8021    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8022    cmp     r1, #'I'                         @ Is int array?
8023    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8024    GOTO_OPCODE(ip)                          @ execute it
8025
8026    /*
8027     * Throw an exception indicating that we have not implemented this
8028     * mode of filled-new-array.
8029     */
8030.LOP_FILLED_NEW_ARRAY_notimpl:
8031    ldr     r0, .L_strInternalError
8032    ldr     r1, .L_strFilledNewArrayNotImpl
8033    bl      dvmThrowException
8034    b       common_exceptionThrown
8035
8036    .if     (!0)                 @ define in one or the other, not both
8037.L_strFilledNewArrayNotImpl:
8038    .word   .LstrFilledNewArrayNotImpl
8039.L_strInternalError:
8040    .word   .LstrInternalError
8041    .endif
8042
8043/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8044
8045    /*
8046     * On entry:
8047     *  r0 holds array class
8048     *  r10 holds AA or BA
8049     */
8050.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8051    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8052    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8053    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8054    .if     1
8055    mov     r1, r10                     @ r1<- AA (length)
8056    .else
8057    mov     r1, r10, lsr #4             @ r1<- B (length)
8058    .endif
8059    cmp     rINST, #'I'                 @ array of ints?
8060    cmpne   rINST, #'L'                 @ array of objects?
8061    cmpne   rINST, #'['                 @ array of arrays?
8062    mov     r9, r1                      @ save length in r9
8063    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8064    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8065    cmp     r0, #0                      @ null return?
8066    beq     common_exceptionThrown      @ alloc failed, handle exception
8067
8068    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8069    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8070    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8071    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8072    subs    r9, r9, #1                  @ length--, check for neg
8073    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8074    bmi     2f                          @ was zero, bail
8075
8076    @ copy values from registers into the array
8077    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8078    .if     1
8079    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80801:  ldr     r3, [r2], #4                @ r3<- *r2++
8081    subs    r9, r9, #1                  @ count--
8082    str     r3, [r0], #4                @ *contents++ = vX
8083    bpl     1b
8084    @ continue at 2
8085    .else
8086    cmp     r9, #4                      @ length was initially 5?
8087    and     r2, r10, #15                @ r2<- A
8088    bne     1f                          @ <= 4 args, branch
8089    GET_VREG(r3, r2)                    @ r3<- vA
8090    sub     r9, r9, #1                  @ count--
8091    str     r3, [r0, #16]               @ contents[4] = vA
80921:  and     r2, r1, #15                 @ r2<- F/E/D/C
8093    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8094    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8095    subs    r9, r9, #1                  @ count--
8096    str     r3, [r0], #4                @ *contents++ = vX
8097    bpl     1b
8098    @ continue at 2
8099    .endif
8100
81012:
8102    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8103    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8104    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8105    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8106    cmp     r1, #'I'                         @ Is int array?
8107    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8108    GOTO_OPCODE(ip)                          @ execute it
8109
8110    /*
8111     * Throw an exception indicating that we have not implemented this
8112     * mode of filled-new-array.
8113     */
8114.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8115    ldr     r0, .L_strInternalError
8116    ldr     r1, .L_strFilledNewArrayNotImpl
8117    bl      dvmThrowException
8118    b       common_exceptionThrown
8119
8120    .if     (!1)                 @ define in one or the other, not both
8121.L_strFilledNewArrayNotImpl:
8122    .word   .LstrFilledNewArrayNotImpl
8123.L_strInternalError:
8124    .word   .LstrInternalError
8125    .endif
8126
8127/* continuation for OP_CMPL_FLOAT */
8128.LOP_CMPL_FLOAT_finish:
8129    SET_VREG(r0, r9)                    @ vAA<- r0
8130    GOTO_OPCODE(ip)                     @ jump to next instruction
8131
8132/* continuation for OP_CMPG_FLOAT */
8133.LOP_CMPG_FLOAT_finish:
8134    SET_VREG(r0, r9)                    @ vAA<- r0
8135    GOTO_OPCODE(ip)                     @ jump to next instruction
8136
8137/* continuation for OP_CMPL_DOUBLE */
8138.LOP_CMPL_DOUBLE_finish:
8139    SET_VREG(r0, r9)                    @ vAA<- r0
8140    GOTO_OPCODE(ip)                     @ jump to next instruction
8141
8142/* continuation for OP_CMPG_DOUBLE */
8143.LOP_CMPG_DOUBLE_finish:
8144    SET_VREG(r0, r9)                    @ vAA<- r0
8145    GOTO_OPCODE(ip)                     @ jump to next instruction
8146
8147/* continuation for OP_CMP_LONG */
8148
8149.LOP_CMP_LONG_less:
8150    mvn     r1, #0                      @ r1<- -1
8151    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8152    @ instead, we just replicate the tail end.
8153    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8154    SET_VREG(r1, r9)                    @ vAA<- r1
8155    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8156    GOTO_OPCODE(ip)                     @ jump to next instruction
8157
8158.LOP_CMP_LONG_greater:
8159    mov     r1, #1                      @ r1<- 1
8160    @ fall through to _finish
8161
8162.LOP_CMP_LONG_finish:
8163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8164    SET_VREG(r1, r9)                    @ vAA<- r1
8165    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8166    GOTO_OPCODE(ip)                     @ jump to next instruction
8167
8168/* continuation for OP_AGET_WIDE */
8169
8170.LOP_AGET_WIDE_finish:
8171    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8172    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8173    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8175    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8176    GOTO_OPCODE(ip)                     @ jump to next instruction
8177
8178/* continuation for OP_APUT_WIDE */
8179
8180.LOP_APUT_WIDE_finish:
8181    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8182    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8183    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8184    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8185    GOTO_OPCODE(ip)                     @ jump to next instruction
8186
8187/* continuation for OP_APUT_OBJECT */
8188    /*
8189     * On entry:
8190     *  rINST = vBB (arrayObj)
8191     *  r9 = vAA (obj)
8192     *  r10 = offset into array (vBB + vCC * width)
8193     */
8194.LOP_APUT_OBJECT_finish:
8195    cmp     r9, #0                      @ storing null reference?
8196    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8197    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8198    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8199    bl      dvmCanPutArrayElement       @ test object type vs. array type
8200    cmp     r0, #0                      @ okay?
8201    beq     common_errArrayStore        @ no
8202    mov     r1, rINST                   @ r1<- arrayObj
8203    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8204    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8205    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8206    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8207    str     r9, [r10]                   @ vBB[vCC]<- vAA
8208    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8209    GOTO_OPCODE(ip)                     @ jump to next instruction
8210.LOP_APUT_OBJECT_skip_check:
8211    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8213    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8214    GOTO_OPCODE(ip)                     @ jump to next instruction
8215
8216/* continuation for OP_IGET */
8217
8218    /*
8219     * Currently:
8220     *  r0 holds resolved field
8221     *  r9 holds object
8222     */
8223.LOP_IGET_finish:
8224    @bl      common_squeak0
8225    cmp     r9, #0                      @ check object for null
8226    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8227    beq     common_errNullObject        @ object was null
8228    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8229    ubfx    r2, rINST, #8, #4           @ r2<- A
8230    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8231    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8232    SET_VREG(r0, r2)                    @ fp[A]<- r0
8233    GOTO_OPCODE(ip)                     @ jump to next instruction
8234
8235/* continuation for OP_IGET_WIDE */
8236
8237    /*
8238     * Currently:
8239     *  r0 holds resolved field
8240     *  r9 holds object
8241     */
8242.LOP_IGET_WIDE_finish:
8243    cmp     r9, #0                      @ check object for null
8244    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8245    beq     common_errNullObject        @ object was null
8246    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8247    ubfx    r2, rINST, #8, #4           @ r2<- A
8248    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8249    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8250    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8251    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8252    GOTO_OPCODE(ip)                     @ jump to next instruction
8253
8254/* continuation for OP_IGET_OBJECT */
8255
8256    /*
8257     * Currently:
8258     *  r0 holds resolved field
8259     *  r9 holds object
8260     */
8261.LOP_IGET_OBJECT_finish:
8262    @bl      common_squeak0
8263    cmp     r9, #0                      @ check object for null
8264    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8265    beq     common_errNullObject        @ object was null
8266    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8267    @ no-op                             @ acquiring load
8268    mov     r2, rINST, lsr #8           @ r2<- A+
8269    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8270    and     r2, r2, #15                 @ r2<- A
8271    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8272    SET_VREG(r0, r2)                    @ fp[A]<- r0
8273    GOTO_OPCODE(ip)                     @ jump to next instruction
8274
8275/* continuation for OP_IGET_BOOLEAN */
8276
8277    /*
8278     * Currently:
8279     *  r0 holds resolved field
8280     *  r9 holds object
8281     */
8282.LOP_IGET_BOOLEAN_finish:
8283    @bl      common_squeak1
8284    cmp     r9, #0                      @ check object for null
8285    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8286    beq     common_errNullObject        @ object was null
8287    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8288    @ no-op                             @ acquiring load
8289    mov     r2, rINST, lsr #8           @ r2<- A+
8290    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8291    and     r2, r2, #15                 @ r2<- A
8292    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8293    SET_VREG(r0, r2)                    @ fp[A]<- r0
8294    GOTO_OPCODE(ip)                     @ jump to next instruction
8295
8296/* continuation for OP_IGET_BYTE */
8297
8298    /*
8299     * Currently:
8300     *  r0 holds resolved field
8301     *  r9 holds object
8302     */
8303.LOP_IGET_BYTE_finish:
8304    @bl      common_squeak2
8305    cmp     r9, #0                      @ check object for null
8306    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8307    beq     common_errNullObject        @ object was null
8308    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8309    @ no-op                             @ acquiring load
8310    mov     r2, rINST, lsr #8           @ r2<- A+
8311    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8312    and     r2, r2, #15                 @ r2<- A
8313    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8314    SET_VREG(r0, r2)                    @ fp[A]<- r0
8315    GOTO_OPCODE(ip)                     @ jump to next instruction
8316
8317/* continuation for OP_IGET_CHAR */
8318
8319    /*
8320     * Currently:
8321     *  r0 holds resolved field
8322     *  r9 holds object
8323     */
8324.LOP_IGET_CHAR_finish:
8325    @bl      common_squeak3
8326    cmp     r9, #0                      @ check object for null
8327    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8328    beq     common_errNullObject        @ object was null
8329    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8330    @ no-op                             @ acquiring load
8331    mov     r2, rINST, lsr #8           @ r2<- A+
8332    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8333    and     r2, r2, #15                 @ r2<- A
8334    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8335    SET_VREG(r0, r2)                    @ fp[A]<- r0
8336    GOTO_OPCODE(ip)                     @ jump to next instruction
8337
8338/* continuation for OP_IGET_SHORT */
8339
8340    /*
8341     * Currently:
8342     *  r0 holds resolved field
8343     *  r9 holds object
8344     */
8345.LOP_IGET_SHORT_finish:
8346    @bl      common_squeak4
8347    cmp     r9, #0                      @ check object for null
8348    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8349    beq     common_errNullObject        @ object was null
8350    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8351    @ no-op                             @ acquiring load
8352    mov     r2, rINST, lsr #8           @ r2<- A+
8353    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8354    and     r2, r2, #15                 @ r2<- A
8355    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8356    SET_VREG(r0, r2)                    @ fp[A]<- r0
8357    GOTO_OPCODE(ip)                     @ jump to next instruction
8358
8359/* continuation for OP_IPUT */
8360
8361    /*
8362     * Currently:
8363     *  r0 holds resolved field
8364     *  r9 holds object
8365     */
8366.LOP_IPUT_finish:
8367    @bl      common_squeak0
8368    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8369    ubfx    r1, rINST, #8, #4           @ r1<- A
8370    cmp     r9, #0                      @ check object for null
8371    GET_VREG(r0, r1)                    @ r0<- fp[A]
8372    beq     common_errNullObject        @ object was null
8373    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8375    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8376    GOTO_OPCODE(ip)                     @ jump to next instruction
8377
8378/* continuation for OP_IPUT_WIDE */
8379
8380    /*
8381     * Currently:
8382     *  r0 holds resolved field
8383     *  r9 holds object
8384     */
8385.LOP_IPUT_WIDE_finish:
8386    ubfx    r2, rINST, #8, #4           @ r2<- A
8387    cmp     r9, #0                      @ check object for null
8388    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8389    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8390    beq     common_errNullObject        @ object was null
8391    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8392    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8393    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8394    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0
8395    GOTO_OPCODE(ip)                     @ jump to next instruction
8396
8397/* continuation for OP_IPUT_OBJECT */
8398
8399    /*
8400     * Currently:
8401     *  r0 holds resolved field
8402     *  r9 holds object
8403     */
8404.LOP_IPUT_OBJECT_finish:
8405    @bl      common_squeak0
8406    mov     r1, rINST, lsr #8           @ r1<- A+
8407    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8408    and     r1, r1, #15                 @ r1<- A
8409    cmp     r9, #0                      @ check object for null
8410    GET_VREG(r0, r1)                    @ r0<- fp[A]
8411    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8412    beq     common_errNullObject        @ object was null
8413    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8415    @ no-op                             @ releasing store
8416    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
8417    cmp     r0, #0                      @ stored a null reference?
8418    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8419    GOTO_OPCODE(ip)                     @ jump to next instruction
8420
8421/* continuation for OP_IPUT_BOOLEAN */
8422
8423    /*
8424     * Currently:
8425     *  r0 holds resolved field
8426     *  r9 holds object
8427     */
8428.LOP_IPUT_BOOLEAN_finish:
8429    @bl      common_squeak1
8430    mov     r1, rINST, lsr #8           @ r1<- A+
8431    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8432    and     r1, r1, #15                 @ r1<- A
8433    cmp     r9, #0                      @ check object for null
8434    GET_VREG(r0, r1)                    @ r0<- fp[A]
8435    beq     common_errNullObject        @ object was null
8436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8438    @ no-op                             @ releasing store
8439    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8440    GOTO_OPCODE(ip)                     @ jump to next instruction
8441
8442/* continuation for OP_IPUT_BYTE */
8443
8444    /*
8445     * Currently:
8446     *  r0 holds resolved field
8447     *  r9 holds object
8448     */
8449.LOP_IPUT_BYTE_finish:
8450    @bl      common_squeak2
8451    mov     r1, rINST, lsr #8           @ r1<- A+
8452    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8453    and     r1, r1, #15                 @ r1<- A
8454    cmp     r9, #0                      @ check object for null
8455    GET_VREG(r0, r1)                    @ r0<- fp[A]
8456    beq     common_errNullObject        @ object was null
8457    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8458    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8459    @ no-op                             @ releasing store
8460    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8461    GOTO_OPCODE(ip)                     @ jump to next instruction
8462
8463/* continuation for OP_IPUT_CHAR */
8464
8465    /*
8466     * Currently:
8467     *  r0 holds resolved field
8468     *  r9 holds object
8469     */
8470.LOP_IPUT_CHAR_finish:
8471    @bl      common_squeak3
8472    mov     r1, rINST, lsr #8           @ r1<- A+
8473    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8474    and     r1, r1, #15                 @ r1<- A
8475    cmp     r9, #0                      @ check object for null
8476    GET_VREG(r0, r1)                    @ r0<- fp[A]
8477    beq     common_errNullObject        @ object was null
8478    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8479    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8480    @ no-op                             @ releasing store
8481    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8482    GOTO_OPCODE(ip)                     @ jump to next instruction
8483
8484/* continuation for OP_IPUT_SHORT */
8485
8486    /*
8487     * Currently:
8488     *  r0 holds resolved field
8489     *  r9 holds object
8490     */
8491.LOP_IPUT_SHORT_finish:
8492    @bl      common_squeak4
8493    mov     r1, rINST, lsr #8           @ r1<- A+
8494    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8495    and     r1, r1, #15                 @ r1<- A
8496    cmp     r9, #0                      @ check object for null
8497    GET_VREG(r0, r1)                    @ r0<- fp[A]
8498    beq     common_errNullObject        @ object was null
8499    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8500    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8501    @ no-op                             @ releasing store
8502    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8503    GOTO_OPCODE(ip)                     @ jump to next instruction
8504
8505/* continuation for OP_SGET */
8506
8507    /*
8508     * Continuation if the field has not yet been resolved.
8509     *  r1: BBBB field ref
8510     */
8511.LOP_SGET_resolve:
8512    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8513    EXPORT_PC()                         @ resolve() could throw, so export now
8514    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8515    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8516    cmp     r0, #0                      @ success?
8517    bne     .LOP_SGET_finish          @ yes, finish
8518    b       common_exceptionThrown      @ no, handle exception
8519
8520/* continuation for OP_SGET_WIDE */
8521
8522    /*
8523     * Continuation if the field has not yet been resolved.
8524     *  r1: BBBB field ref
8525     *
8526     * Returns StaticField pointer in r0.
8527     */
8528.LOP_SGET_WIDE_resolve:
8529    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8530    EXPORT_PC()                         @ resolve() could throw, so export now
8531    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8532    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8533    cmp     r0, #0                      @ success?
8534    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8535    b       common_exceptionThrown      @ no, handle exception
8536
8537/* continuation for OP_SGET_OBJECT */
8538
8539    /*
8540     * Continuation if the field has not yet been resolved.
8541     *  r1: BBBB field ref
8542     */
8543.LOP_SGET_OBJECT_resolve:
8544    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8545    EXPORT_PC()                         @ resolve() could throw, so export now
8546    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8547    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8548    cmp     r0, #0                      @ success?
8549    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8550    b       common_exceptionThrown      @ no, handle exception
8551
8552/* continuation for OP_SGET_BOOLEAN */
8553
8554    /*
8555     * Continuation if the field has not yet been resolved.
8556     *  r1: BBBB field ref
8557     */
8558.LOP_SGET_BOOLEAN_resolve:
8559    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8560    EXPORT_PC()                         @ resolve() could throw, so export now
8561    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8562    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8563    cmp     r0, #0                      @ success?
8564    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8565    b       common_exceptionThrown      @ no, handle exception
8566
8567/* continuation for OP_SGET_BYTE */
8568
8569    /*
8570     * Continuation if the field has not yet been resolved.
8571     *  r1: BBBB field ref
8572     */
8573.LOP_SGET_BYTE_resolve:
8574    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8575    EXPORT_PC()                         @ resolve() could throw, so export now
8576    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8577    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8578    cmp     r0, #0                      @ success?
8579    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8580    b       common_exceptionThrown      @ no, handle exception
8581
8582/* continuation for OP_SGET_CHAR */
8583
8584    /*
8585     * Continuation if the field has not yet been resolved.
8586     *  r1: BBBB field ref
8587     */
8588.LOP_SGET_CHAR_resolve:
8589    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8590    EXPORT_PC()                         @ resolve() could throw, so export now
8591    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8592    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8593    cmp     r0, #0                      @ success?
8594    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8595    b       common_exceptionThrown      @ no, handle exception
8596
8597/* continuation for OP_SGET_SHORT */
8598
8599    /*
8600     * Continuation if the field has not yet been resolved.
8601     *  r1: BBBB field ref
8602     */
8603.LOP_SGET_SHORT_resolve:
8604    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8605    EXPORT_PC()                         @ resolve() could throw, so export now
8606    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8607    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8608    cmp     r0, #0                      @ success?
8609    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8610    b       common_exceptionThrown      @ no, handle exception
8611
8612/* continuation for OP_SPUT */
8613
8614    /*
8615     * Continuation if the field has not yet been resolved.
8616     *  r1: BBBB field ref
8617     */
8618.LOP_SPUT_resolve:
8619    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8620    EXPORT_PC()                         @ resolve() could throw, so export now
8621    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8622    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8623    cmp     r0, #0                      @ success?
8624    bne     .LOP_SPUT_finish          @ yes, finish
8625    b       common_exceptionThrown      @ no, handle exception
8626
8627/* continuation for OP_SPUT_WIDE */
8628
8629    /*
8630     * Continuation if the field has not yet been resolved.
8631     *  r1: BBBB field ref
8632     *  r9: &fp[AA]
8633     *
8634     * Returns StaticField pointer in r2.
8635     */
8636.LOP_SPUT_WIDE_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    mov     r2, r0                      @ copy to r2
8643    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8644    b       common_exceptionThrown      @ no, handle exception
8645
8646/* continuation for OP_SPUT_OBJECT */
8647.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8648    mov     r2, rINST, lsr #8           @ r2<- AA
8649    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8650    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8651    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8652    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
8653    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8654    @ no-op                             @ releasing store
8655    str     r1, [r0, #offStaticField_value]  @ field<- vAA
8656    cmp     r1, #0                      @ stored a null object?
8657    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
8658    GOTO_OPCODE(ip)                     @ jump to next instruction
8659
8660/* continuation for OP_SPUT_BOOLEAN */
8661
8662    /*
8663     * Continuation if the field has not yet been resolved.
8664     *  r1: BBBB field ref
8665     */
8666.LOP_SPUT_BOOLEAN_resolve:
8667    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8668    EXPORT_PC()                         @ resolve() could throw, so export now
8669    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8670    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8671    cmp     r0, #0                      @ success?
8672    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8673    b       common_exceptionThrown      @ no, handle exception
8674
8675/* continuation for OP_SPUT_BYTE */
8676
8677    /*
8678     * Continuation if the field has not yet been resolved.
8679     *  r1: BBBB field ref
8680     */
8681.LOP_SPUT_BYTE_resolve:
8682    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8683    EXPORT_PC()                         @ resolve() could throw, so export now
8684    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8685    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8686    cmp     r0, #0                      @ success?
8687    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8688    b       common_exceptionThrown      @ no, handle exception
8689
8690/* continuation for OP_SPUT_CHAR */
8691
8692    /*
8693     * Continuation if the field has not yet been resolved.
8694     *  r1: BBBB field ref
8695     */
8696.LOP_SPUT_CHAR_resolve:
8697    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8698    EXPORT_PC()                         @ resolve() could throw, so export now
8699    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8700    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8701    cmp     r0, #0                      @ success?
8702    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8703    b       common_exceptionThrown      @ no, handle exception
8704
8705/* continuation for OP_SPUT_SHORT */
8706
8707    /*
8708     * Continuation if the field has not yet been resolved.
8709     *  r1: BBBB field ref
8710     */
8711.LOP_SPUT_SHORT_resolve:
8712    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8713    EXPORT_PC()                         @ resolve() could throw, so export now
8714    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8715    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8716    cmp     r0, #0                      @ success?
8717    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8718    b       common_exceptionThrown      @ no, handle exception
8719
8720/* continuation for OP_INVOKE_VIRTUAL */
8721
8722    /*
8723     * At this point:
8724     *  r0 = resolved base method
8725     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8726     */
8727.LOP_INVOKE_VIRTUAL_continue:
8728    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8729    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8730    cmp     r1, #0                      @ is "this" null?
8731    beq     common_errNullObject        @ null "this", throw exception
8732    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8733    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8734    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8735    bl      common_invokeMethodNoRange @ continue on
8736
8737/* continuation for OP_INVOKE_SUPER */
8738
8739    /*
8740     * At this point:
8741     *  r0 = resolved base method
8742     *  r9 = method->clazz
8743     */
8744.LOP_INVOKE_SUPER_continue:
8745    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8746    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8747    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8748    EXPORT_PC()                         @ must export for invoke
8749    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8750    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8751    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8752    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8753    bl      common_invokeMethodNoRange @ continue on
8754
8755.LOP_INVOKE_SUPER_resolve:
8756    mov     r0, r9                      @ r0<- method->clazz
8757    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8758    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8759    cmp     r0, #0                      @ got null?
8760    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8761    b       common_exceptionThrown      @ yes, handle exception
8762
8763    /*
8764     * Throw a NoSuchMethodError with the method name as the message.
8765     *  r0 = resolved base method
8766     */
8767.LOP_INVOKE_SUPER_nsm:
8768    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8769    b       common_errNoSuchMethod
8770
8771/* continuation for OP_INVOKE_DIRECT */
8772
8773    /*
8774     * On entry:
8775     *  r1 = reference (BBBB or CCCC)
8776     *  r10 = "this" register
8777     */
8778.LOP_INVOKE_DIRECT_resolve:
8779    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8780    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8781    mov     r2, #METHOD_DIRECT          @ resolver method type
8782    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8783    cmp     r0, #0                      @ got null?
8784    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8785    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8786    b       common_exceptionThrown      @ yes, handle exception
8787
8788/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8789
8790    /*
8791     * At this point:
8792     *  r0 = resolved base method
8793     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8794     */
8795.LOP_INVOKE_VIRTUAL_RANGE_continue:
8796    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8797    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8798    cmp     r1, #0                      @ is "this" null?
8799    beq     common_errNullObject        @ null "this", throw exception
8800    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8801    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8802    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8803    bl      common_invokeMethodRange @ continue on
8804
8805/* continuation for OP_INVOKE_SUPER_RANGE */
8806
8807    /*
8808     * At this point:
8809     *  r0 = resolved base method
8810     *  r9 = method->clazz
8811     */
8812.LOP_INVOKE_SUPER_RANGE_continue:
8813    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8814    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8815    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8816    EXPORT_PC()                         @ must export for invoke
8817    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8818    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8819    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8820    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8821    bl      common_invokeMethodRange @ continue on
8822
8823.LOP_INVOKE_SUPER_RANGE_resolve:
8824    mov     r0, r9                      @ r0<- method->clazz
8825    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8826    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8827    cmp     r0, #0                      @ got null?
8828    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8829    b       common_exceptionThrown      @ yes, handle exception
8830
8831    /*
8832     * Throw a NoSuchMethodError with the method name as the message.
8833     *  r0 = resolved base method
8834     */
8835.LOP_INVOKE_SUPER_RANGE_nsm:
8836    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8837    b       common_errNoSuchMethod
8838
8839/* continuation for OP_INVOKE_DIRECT_RANGE */
8840
8841    /*
8842     * On entry:
8843     *  r1 = reference (BBBB or CCCC)
8844     *  r10 = "this" register
8845     */
8846.LOP_INVOKE_DIRECT_RANGE_resolve:
8847    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8848    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8849    mov     r2, #METHOD_DIRECT          @ resolver method type
8850    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8851    cmp     r0, #0                      @ got null?
8852    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8853    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8854    b       common_exceptionThrown      @ yes, handle exception
8855
8856/* continuation for OP_FLOAT_TO_LONG */
8857/*
8858 * Convert the float in r0 to a long in r0/r1.
8859 *
8860 * We have to clip values to long min/max per the specification.  The
8861 * expected common case is a "reasonable" value that converts directly
8862 * to modest integer.  The EABI convert function isn't doing this for us.
8863 */
8864f2l_doconv:
8865    stmfd   sp!, {r4, lr}
8866    mov     r1, #0x5f000000             @ (float)maxlong
8867    mov     r4, r0
8868    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8869    cmp     r0, #0                      @ nonzero == yes
8870    mvnne   r0, #0                      @ return maxlong (7fffffff)
8871    mvnne   r1, #0x80000000
8872    ldmnefd sp!, {r4, pc}
8873
8874    mov     r0, r4                      @ recover arg
8875    mov     r1, #0xdf000000             @ (float)minlong
8876    bl      __aeabi_fcmple              @ is arg <= minlong?
8877    cmp     r0, #0                      @ nonzero == yes
8878    movne   r0, #0                      @ return minlong (80000000)
8879    movne   r1, #0x80000000
8880    ldmnefd sp!, {r4, pc}
8881
8882    mov     r0, r4                      @ recover arg
8883    mov     r1, r4
8884    bl      __aeabi_fcmpeq              @ is arg == self?
8885    cmp     r0, #0                      @ zero == no
8886    moveq   r1, #0                      @ return zero for NaN
8887    ldmeqfd sp!, {r4, pc}
8888
8889    mov     r0, r4                      @ recover arg
8890    bl      __aeabi_f2lz                @ convert float to long
8891    ldmfd   sp!, {r4, pc}
8892
8893/* continuation for OP_DOUBLE_TO_LONG */
8894/*
8895 * Convert the double in r0/r1 to a long in r0/r1.
8896 *
8897 * We have to clip values to long min/max per the specification.  The
8898 * expected common case is a "reasonable" value that converts directly
8899 * to modest integer.  The EABI convert function isn't doing this for us.
8900 */
8901d2l_doconv:
8902    stmfd   sp!, {r4, r5, lr}           @ save regs
8903    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8904    add     r3, #0x00e00000             @  0x43e00000
8905    mov     r2, #0                      @ maxlong, as a double (low word)
8906    sub     sp, sp, #4                  @ align for EABI
8907    mov     r4, r0                      @ save a copy of r0
8908    mov     r5, r1                      @  and r1
8909    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8910    cmp     r0, #0                      @ nonzero == yes
8911    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8912    mvnne   r1, #0x80000000
8913    bne     1f
8914
8915    mov     r0, r4                      @ recover arg
8916    mov     r1, r5
8917    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8918    add     r3, #0x00e00000             @  0xc3e00000
8919    mov     r2, #0                      @ minlong, as a double (low word)
8920    bl      __aeabi_dcmple              @ is arg <= minlong?
8921    cmp     r0, #0                      @ nonzero == yes
8922    movne   r0, #0                      @ return minlong (8000000000000000)
8923    movne   r1, #0x80000000
8924    bne     1f
8925
8926    mov     r0, r4                      @ recover arg
8927    mov     r1, r5
8928    mov     r2, r4                      @ compare against self
8929    mov     r3, r5
8930    bl      __aeabi_dcmpeq              @ is arg == self?
8931    cmp     r0, #0                      @ zero == no
8932    moveq   r1, #0                      @ return zero for NaN
8933    beq     1f
8934
8935    mov     r0, r4                      @ recover arg
8936    mov     r1, r5
8937    bl      __aeabi_d2lz                @ convert double to long
8938
89391:
8940    add     sp, sp, #4
8941    ldmfd   sp!, {r4, r5, pc}
8942
8943/* continuation for OP_MUL_LONG */
8944
8945.LOP_MUL_LONG_finish:
8946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8947    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
8948    GOTO_OPCODE(ip)                     @ jump to next instruction
8949
8950/* continuation for OP_SHL_LONG */
8951
8952.LOP_SHL_LONG_finish:
8953    mov     r0, r0, asl r2              @  r0<- r0 << r2
8954    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8955    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8956    GOTO_OPCODE(ip)                     @ jump to next instruction
8957
8958/* continuation for OP_SHR_LONG */
8959
8960.LOP_SHR_LONG_finish:
8961    mov     r1, r1, asr r2              @  r1<- r1 >> r2
8962    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8963    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8964    GOTO_OPCODE(ip)                     @ jump to next instruction
8965
8966/* continuation for OP_USHR_LONG */
8967
8968.LOP_USHR_LONG_finish:
8969    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
8970    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8971    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8972    GOTO_OPCODE(ip)                     @ jump to next instruction
8973
8974/* continuation for OP_SHL_LONG_2ADDR */
8975
8976.LOP_SHL_LONG_2ADDR_finish:
8977    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8978    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8979    GOTO_OPCODE(ip)                     @ jump to next instruction
8980
8981/* continuation for OP_SHR_LONG_2ADDR */
8982
8983.LOP_SHR_LONG_2ADDR_finish:
8984    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8985    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8986    GOTO_OPCODE(ip)                     @ jump to next instruction
8987
8988/* continuation for OP_USHR_LONG_2ADDR */
8989
8990.LOP_USHR_LONG_2ADDR_finish:
8991    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8992    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
8993    GOTO_OPCODE(ip)                     @ jump to next instruction
8994
8995/* continuation for OP_IGET_VOLATILE */
8996
8997    /*
8998     * Currently:
8999     *  r0 holds resolved field
9000     *  r9 holds object
9001     */
9002.LOP_IGET_VOLATILE_finish:
9003    @bl      common_squeak0
9004    cmp     r9, #0                      @ check object for null
9005    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9006    beq     common_errNullObject        @ object was null
9007    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9008    SMP_DMB                            @ acquiring load
9009    mov     r2, rINST, lsr #8           @ r2<- A+
9010    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9011    and     r2, r2, #15                 @ r2<- A
9012    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9013    SET_VREG(r0, r2)                    @ fp[A]<- r0
9014    GOTO_OPCODE(ip)                     @ jump to next instruction
9015
9016/* continuation for OP_IPUT_VOLATILE */
9017
9018    /*
9019     * Currently:
9020     *  r0 holds resolved field
9021     *  r9 holds object
9022     */
9023.LOP_IPUT_VOLATILE_finish:
9024    @bl      common_squeak0
9025    mov     r1, rINST, lsr #8           @ r1<- A+
9026    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9027    and     r1, r1, #15                 @ r1<- A
9028    cmp     r9, #0                      @ check object for null
9029    GET_VREG(r0, r1)                    @ r0<- fp[A]
9030    beq     common_errNullObject        @ object was null
9031    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9032    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9033    SMP_DMB                            @ releasing store
9034    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9035    GOTO_OPCODE(ip)                     @ jump to next instruction
9036
9037/* continuation for OP_SGET_VOLATILE */
9038
9039    /*
9040     * Continuation if the field has not yet been resolved.
9041     *  r1: BBBB field ref
9042     */
9043.LOP_SGET_VOLATILE_resolve:
9044    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9045    EXPORT_PC()                         @ resolve() could throw, so export now
9046    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9047    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9048    cmp     r0, #0                      @ success?
9049    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9050    b       common_exceptionThrown      @ no, handle exception
9051
9052/* continuation for OP_SPUT_VOLATILE */
9053
9054    /*
9055     * Continuation if the field has not yet been resolved.
9056     *  r1: BBBB field ref
9057     */
9058.LOP_SPUT_VOLATILE_resolve:
9059    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9060    EXPORT_PC()                         @ resolve() could throw, so export now
9061    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9062    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9063    cmp     r0, #0                      @ success?
9064    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9065    b       common_exceptionThrown      @ no, handle exception
9066
9067/* continuation for OP_IGET_OBJECT_VOLATILE */
9068
9069    /*
9070     * Currently:
9071     *  r0 holds resolved field
9072     *  r9 holds object
9073     */
9074.LOP_IGET_OBJECT_VOLATILE_finish:
9075    @bl      common_squeak0
9076    cmp     r9, #0                      @ check object for null
9077    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9078    beq     common_errNullObject        @ object was null
9079    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9080    SMP_DMB                            @ acquiring load
9081    mov     r2, rINST, lsr #8           @ r2<- A+
9082    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9083    and     r2, r2, #15                 @ r2<- A
9084    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9085    SET_VREG(r0, r2)                    @ fp[A]<- r0
9086    GOTO_OPCODE(ip)                     @ jump to next instruction
9087
9088/* continuation for OP_IGET_WIDE_VOLATILE */
9089
9090    /*
9091     * Currently:
9092     *  r0 holds resolved field
9093     *  r9 holds object
9094     */
9095.LOP_IGET_WIDE_VOLATILE_finish:
9096    cmp     r9, #0                      @ check object for null
9097    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9098    beq     common_errNullObject        @ object was null
9099    .if     1
9100    add     r0, r9, r3                  @ r0<- address of field
9101    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9102    .else
9103    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9104    .endif
9105    mov     r2, rINST, lsr #8           @ r2<- A+
9106    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9107    and     r2, r2, #15                 @ r2<- A
9108    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9109    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9110    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9111    GOTO_OPCODE(ip)                     @ jump to next instruction
9112
9113/* continuation for OP_IPUT_WIDE_VOLATILE */
9114
9115    /*
9116     * Currently:
9117     *  r0 holds resolved field
9118     *  r9 holds object
9119     */
9120.LOP_IPUT_WIDE_VOLATILE_finish:
9121    mov     r2, rINST, lsr #8           @ r2<- A+
9122    cmp     r9, #0                      @ check object for null
9123    and     r2, r2, #15                 @ r2<- A
9124    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9125    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9126    beq     common_errNullObject        @ object was null
9127    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9128    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9129    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9130    .if     1
9131    add     r2, r9, r3                  @ r2<- target address
9132    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9133    .else
9134    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9135    .endif
9136    GOTO_OPCODE(r10)                    @ jump to next instruction
9137
9138/* continuation for OP_SGET_WIDE_VOLATILE */
9139
9140    /*
9141     * Continuation if the field has not yet been resolved.
9142     *  r1: BBBB field ref
9143     *
9144     * Returns StaticField pointer in r0.
9145     */
9146.LOP_SGET_WIDE_VOLATILE_resolve:
9147    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9148    EXPORT_PC()                         @ resolve() could throw, so export now
9149    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9150    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9151    cmp     r0, #0                      @ success?
9152    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9153    b       common_exceptionThrown      @ no, handle exception
9154
9155/* continuation for OP_SPUT_WIDE_VOLATILE */
9156
9157    /*
9158     * Continuation if the field has not yet been resolved.
9159     *  r1: BBBB field ref
9160     *  r9: &fp[AA]
9161     *
9162     * Returns StaticField pointer in r2.
9163     */
9164.LOP_SPUT_WIDE_VOLATILE_resolve:
9165    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9166    EXPORT_PC()                         @ resolve() could throw, so export now
9167    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9168    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9169    cmp     r0, #0                      @ success?
9170    mov     r2, r0                      @ copy to r2
9171    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9172    b       common_exceptionThrown      @ no, handle exception
9173
9174/* continuation for OP_EXECUTE_INLINE */
9175
9176    /*
9177     * Extract args, call function.
9178     *  r0 = #of args (0-4)
9179     *  r10 = call index
9180     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9181     *
9182     * Other ideas:
9183     * - Use a jump table from the main piece to jump directly into the
9184     *   AND/LDR pairs.  Costs a data load, saves a branch.
9185     * - Have five separate pieces that do the loading, so we can work the
9186     *   interleave a little better.  Increases code size.
9187     */
9188.LOP_EXECUTE_INLINE_continue:
9189    rsb     r0, r0, #4                  @ r0<- 4-r0
9190    FETCH(r9, 2)                        @ r9<- FEDC
9191    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9192    bl      common_abort                @ (skipped due to ARM prefetch)
91934:  and     ip, r9, #0xf000             @ isolate F
9194    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
91953:  and     ip, r9, #0x0f00             @ isolate E
9196    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
91972:  and     ip, r9, #0x00f0             @ isolate D
9198    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
91991:  and     ip, r9, #0x000f             @ isolate C
9200    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92010:
9202    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9203    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9204    @ (not reached)
9205
9206.LOP_EXECUTE_INLINE_table:
9207    .word   gDvmInlineOpsTable
9208
9209/* continuation for OP_EXECUTE_INLINE_RANGE */
9210
9211    /*
9212     * Extract args, call function.
9213     *  r0 = #of args (0-4)
9214     *  r10 = call index
9215     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9216     */
9217.LOP_EXECUTE_INLINE_RANGE_continue:
9218    rsb     r0, r0, #4                  @ r0<- 4-r0
9219    FETCH(r9, 2)                        @ r9<- CCCC
9220    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9221    bl      common_abort                @ (skipped due to ARM prefetch)
92224:  add     ip, r9, #3                  @ base+3
9223    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92243:  add     ip, r9, #2                  @ base+2
9225    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92262:  add     ip, r9, #1                  @ base+1
9227    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92281:  add     ip, r9, #0                  @ (nop)
9229    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92300:
9231    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9232    ldr     pc, [r9, r10, lsl #4]       @ sizeof=16, "func" is first entry
9233    @ (not reached)
9234
9235.LOP_EXECUTE_INLINE_RANGE_table:
9236    .word   gDvmInlineOpsTable
9237
9238/* continuation for OP_IPUT_OBJECT_VOLATILE */
9239
9240    /*
9241     * Currently:
9242     *  r0 holds resolved field
9243     *  r9 holds object
9244     */
9245.LOP_IPUT_OBJECT_VOLATILE_finish:
9246    @bl      common_squeak0
9247    mov     r1, rINST, lsr #8           @ r1<- A+
9248    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9249    and     r1, r1, #15                 @ r1<- A
9250    cmp     r9, #0                      @ check object for null
9251    GET_VREG(r0, r1)                    @ r0<- fp[A]
9252    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9253    beq     common_errNullObject        @ object was null
9254    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9255    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9256    SMP_DMB                            @ releasing store
9257    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
9258    cmp     r0, #0                      @ stored a null reference?
9259    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9260    GOTO_OPCODE(ip)                     @ jump to next instruction
9261
9262/* continuation for OP_SGET_OBJECT_VOLATILE */
9263
9264    /*
9265     * Continuation if the field has not yet been resolved.
9266     *  r1: BBBB field ref
9267     */
9268.LOP_SGET_OBJECT_VOLATILE_resolve:
9269    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9270    EXPORT_PC()                         @ resolve() could throw, so export now
9271    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9272    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9273    cmp     r0, #0                      @ success?
9274    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9275    b       common_exceptionThrown      @ no, handle exception
9276
9277/* continuation for OP_SPUT_OBJECT_VOLATILE */
9278.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9279    mov     r2, rINST, lsr #8           @ r2<- AA
9280    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9281    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9282    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9283    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9285    SMP_DMB                            @ releasing store
9286    str     r1, [r0, #offStaticField_value]  @ field<- vAA
9287    cmp     r1, #0                      @ stored a null object?
9288    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9289    GOTO_OPCODE(ip)                     @ jump to next instruction
9290
9291    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9292    .global dvmAsmSisterEnd
9293dvmAsmSisterEnd:
9294
9295/* File: armv5te/footer.S */
9296
9297/*
9298 * ===========================================================================
9299 *  Common subroutines and data
9300 * ===========================================================================
9301 */
9302
9303
9304
9305    .text
9306    .align  2
9307
9308#if defined(WITH_JIT)
9309#if defined(WITH_SELF_VERIFICATION)
9310    .global dvmJitToInterpPunt
9311dvmJitToInterpPunt:
9312    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9313    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9314    mov    r3, #0
9315    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9316    b      jitSVShadowRunEnd            @ doesn't return
9317
9318    .global dvmJitToInterpSingleStep
9319dvmJitToInterpSingleStep:
9320    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9321    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9322    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9323    b      jitSVShadowRunEnd            @ doesn't return
9324
9325    .global dvmJitToInterpNoChainNoProfile
9326dvmJitToInterpNoChainNoProfile:
9327    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9328    mov    r0,rPC                       @ pass our target PC
9329    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9330    mov    r3, #0                       @ 0 means !inJitCodeCache
9331    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9332    b      jitSVShadowRunEnd            @ doesn't return
9333
9334    .global dvmJitToInterpTraceSelectNoChain
9335dvmJitToInterpTraceSelectNoChain:
9336    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9337    mov    r0,rPC                       @ pass our target PC
9338    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9339    mov    r3, #0                       @ 0 means !inJitCodeCache
9340    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9341    b      jitSVShadowRunEnd            @ doesn't return
9342
9343    .global dvmJitToInterpTraceSelect
9344dvmJitToInterpTraceSelect:
9345    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9346    ldr    r0,[lr, #-1]                 @ pass our target PC
9347    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9348    mov    r3, #0                       @ 0 means !inJitCodeCache
9349    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9350    b      jitSVShadowRunEnd            @ doesn't return
9351
9352    .global dvmJitToInterpBackwardBranch
9353dvmJitToInterpBackwardBranch:
9354    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9355    ldr    r0,[lr, #-1]                 @ pass our target PC
9356    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9357    mov    r3, #0                       @ 0 means !inJitCodeCache
9358    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9359    b      jitSVShadowRunEnd            @ doesn't return
9360
9361    .global dvmJitToInterpNormal
9362dvmJitToInterpNormal:
9363    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9364    ldr    r0,[lr, #-1]                 @ pass our target PC
9365    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9366    mov    r3, #0                       @ 0 means !inJitCodeCache
9367    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9368    b      jitSVShadowRunEnd            @ doesn't return
9369
9370    .global dvmJitToInterpNoChain
9371dvmJitToInterpNoChain:
9372    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9373    mov    r0,rPC                       @ pass our target PC
9374    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9375    mov    r3, #0                       @ 0 means !inJitCodeCache
9376    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9377    b      jitSVShadowRunEnd            @ doesn't return
9378#else
9379/*
9380 * Return from the translation cache to the interpreter when the compiler is
9381 * having issues translating/executing a Dalvik instruction. We have to skip
9382 * the code cache lookup otherwise it is possible to indefinitely bouce
9383 * between the interpreter and the code cache if the instruction that fails
9384 * to be compiled happens to be at a trace start.
9385 */
9386    .global dvmJitToInterpPunt
9387dvmJitToInterpPunt:
9388    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9389    mov    rPC, r0
9390#if defined(WITH_JIT_TUNING)
9391    mov    r0,lr
9392    bl     dvmBumpPunt;
9393#endif
9394    EXPORT_PC()
9395    mov    r0, #0
9396    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9397    adrl   rIBASE, dvmAsmInstructionStart
9398    FETCH_INST()
9399    GET_INST_OPCODE(ip)
9400    GOTO_OPCODE(ip)
9401
9402/*
9403 * Return to the interpreter to handle a single instruction.
9404 * On entry:
9405 *    r0 <= PC
9406 *    r1 <= PC of resume instruction
9407 *    lr <= resume point in translation
9408 */
9409    .global dvmJitToInterpSingleStep
9410dvmJitToInterpSingleStep:
9411    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9412    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9413    mov    r1,#kInterpEntryInstr
9414    @ enum is 4 byte in aapcs-EABI
9415    str    r1, [rGLUE, #offGlue_entryPoint]
9416    mov    rPC,r0
9417    EXPORT_PC()
9418
9419    adrl   rIBASE, dvmAsmInstructionStart
9420    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9421    str    r2,[rGLUE,#offGlue_jitState]
9422    mov    r1,#1                  @ set changeInterp to bail to debug interp
9423    b      common_gotoBail
9424
9425/*
9426 * Return from the translation cache and immediately request
9427 * a translation for the exit target.  Commonly used for callees.
9428 */
9429    .global dvmJitToInterpTraceSelectNoChain
9430dvmJitToInterpTraceSelectNoChain:
9431#if defined(WITH_JIT_TUNING)
9432    bl     dvmBumpNoChain
9433#endif
9434    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9435    mov    r0,rPC
9436    bl     dvmJitGetCodeAddr        @ Is there a translation?
9437    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9438    mov    r1, rPC                  @ arg1 of translation may need this
9439    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9440    cmp    r0,#0                    @ !0 means translation exists
9441    bxne   r0                       @ continue native execution if so
9442    b      2f                       @ branch over to use the interpreter
9443
9444/*
9445 * Return from the translation cache and immediately request
9446 * a translation for the exit target.  Commonly used following
9447 * invokes.
9448 */
9449    .global dvmJitToInterpTraceSelect
9450dvmJitToInterpTraceSelect:
9451    ldr    rPC,[lr, #-1]           @ get our target PC
9452    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9453    add    rINST,lr,#-5            @ save start of chain branch
9454    add    rINST, #-4              @  .. which is 9 bytes back
9455    mov    r0,rPC
9456    bl     dvmJitGetCodeAddr       @ Is there a translation?
9457    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9458    cmp    r0,#0
9459    beq    2f
9460    mov    r1,rINST
9461    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9462    mov    r1, rPC                  @ arg1 of translation may need this
9463    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9464    cmp    r0,#0                    @ successful chain?
9465    bxne   r0                       @ continue native execution
9466    b      toInterpreter            @ didn't chain - resume with interpreter
9467
9468/* No translation, so request one if profiling isn't disabled*/
94692:
9470    adrl   rIBASE, dvmAsmInstructionStart
9471    GET_JIT_PROF_TABLE(r0)
9472    FETCH_INST()
9473    cmp    r0, #0
9474    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9475    bne    common_selectTrace
9476    GET_INST_OPCODE(ip)
9477    GOTO_OPCODE(ip)
9478
9479/*
9480 * Return from the translation cache to the interpreter.
9481 * The return was done with a BLX from thumb mode, and
9482 * the following 32-bit word contains the target rPC value.
9483 * Note that lr (r14) will have its low-order bit set to denote
9484 * its thumb-mode origin.
9485 *
9486 * We'll need to stash our lr origin away, recover the new
9487 * target and then check to see if there is a translation available
9488 * for our new target.  If so, we do a translation chain and
9489 * go back to native execution.  Otherwise, it's back to the
9490 * interpreter (after treating this entry as a potential
9491 * trace start).
9492 */
9493    .global dvmJitToInterpNormal
9494dvmJitToInterpNormal:
9495    ldr    rPC,[lr, #-1]           @ get our target PC
9496    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9497    add    rINST,lr,#-5            @ save start of chain branch
9498    add    rINST,#-4               @ .. which is 9 bytes back
9499#if defined(WITH_JIT_TUNING)
9500    bl     dvmBumpNormal
9501#endif
9502    mov    r0,rPC
9503    bl     dvmJitGetCodeAddr        @ Is there a translation?
9504    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9505    cmp    r0,#0
9506    beq    toInterpreter            @ go if not, otherwise do chain
9507    mov    r1,rINST
9508    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9509    mov    r1, rPC                  @ arg1 of translation may need this
9510    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9511    cmp    r0,#0                    @ successful chain?
9512    bxne   r0                       @ continue native execution
9513    b      toInterpreter            @ didn't chain - resume with interpreter
9514
9515/*
9516 * Return from the translation cache to the interpreter to do method invocation.
9517 * Check if translation exists for the callee, but don't chain to it.
9518 */
9519    .global dvmJitToInterpNoChainNoProfile
9520dvmJitToInterpNoChainNoProfile:
9521#if defined(WITH_JIT_TUNING)
9522    bl     dvmBumpNoChain
9523#endif
9524    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9525    mov    r0,rPC
9526    bl     dvmJitGetCodeAddr        @ Is there a translation?
9527    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9528    mov    r1, rPC                  @ arg1 of translation may need this
9529    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9530    cmp    r0,#0
9531    bxne   r0                       @ continue native execution if so
9532    EXPORT_PC()
9533    adrl   rIBASE, dvmAsmInstructionStart
9534    FETCH_INST()
9535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9536    GOTO_OPCODE(ip)                     @ jump to next instruction
9537
9538/*
9539 * Return from the translation cache to the interpreter to do method invocation.
9540 * Check if translation exists for the callee, but don't chain to it.
9541 */
9542    .global dvmJitToInterpNoChain
9543dvmJitToInterpNoChain:
9544#if defined(WITH_JIT_TUNING)
9545    bl     dvmBumpNoChain
9546#endif
9547    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9548    mov    r0,rPC
9549    bl     dvmJitGetCodeAddr        @ Is there a translation?
9550    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9551    mov    r1, rPC                  @ arg1 of translation may need this
9552    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9553    cmp    r0,#0
9554    bxne   r0                       @ continue native execution if so
9555#endif
9556
9557/*
9558 * No translation, restore interpreter regs and start interpreting.
9559 * rGLUE & rFP were preserved in the translated code, and rPC has
9560 * already been restored by the time we get here.  We'll need to set
9561 * up rIBASE & rINST, and load the address of the JitTable into r0.
9562 */
9563toInterpreter:
9564    EXPORT_PC()
9565    adrl   rIBASE, dvmAsmInstructionStart
9566    FETCH_INST()
9567    GET_JIT_PROF_TABLE(r0)
9568    @ NOTE: intended fallthrough
9569
9570/*
9571 * Common code to update potential trace start counter, and initiate
9572 * a trace-build if appropriate.  On entry, rPC should point to the
9573 * next instruction to execute, and rINST should be already loaded with
9574 * the next opcode word, and r0 holds a pointer to the jit profile
9575 * table (pJitProfTable).
9576 */
9577common_testUpdateProfile:
9578    cmp     r0,#0
9579    GET_INST_OPCODE(ip)
9580    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9581
9582common_updateProfile:
9583    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9584    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9585    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9586    GET_INST_OPCODE(ip)
9587    subs    r1,r1,#1           @ decrement counter
9588    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9589    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9590
9591/*
9592 * Here, we switch to the debug interpreter to request
9593 * trace selection.  First, though, check to see if there
9594 * is already a native translation in place (and, if so,
9595 * jump to it now).
9596 */
9597    GET_JIT_THRESHOLD(r1)
9598    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9599    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9600    EXPORT_PC()
9601    mov     r0,rPC
9602    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9603    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9604    mov     r1, rPC                     @ arg1 of translation may need this
9605    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9606    cmp     r0,#0
9607#if !defined(WITH_SELF_VERIFICATION)
9608    bxne    r0                          @ jump to the translation
9609    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9610    @ fall-through to common_selectTrace
9611#else
9612    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9613    beq     common_selectTrace
9614    /*
9615     * At this point, we have a target translation.  However, if
9616     * that translation is actually the interpret-only pseudo-translation
9617     * we want to treat it the same as no translation.
9618     */
9619    mov     r10, r0                     @ save target
9620    bl      dvmCompilerGetInterpretTemplate
9621    cmp     r0, r10                     @ special case?
9622    bne     jitSVShadowRunStart         @ set up self verification shadow space
9623    @ Need to clear the inJitCodeCache flag
9624    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
9625    mov    r3, #0                       @ 0 means not in the JIT code cache
9626    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9627    GET_INST_OPCODE(ip)
9628    GOTO_OPCODE(ip)
9629    /* no return */
9630#endif
9631
9632/*
9633 * On entry:
9634 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9635 */
9636common_selectTrace:
9637    str     r2,[rGLUE,#offGlue_jitState]
9638    mov     r2,#kInterpEntryInstr       @ normal entry reason
9639    str     r2,[rGLUE,#offGlue_entryPoint]
9640    mov     r1,#1                       @ set changeInterp
9641    b       common_gotoBail
9642
9643#if defined(WITH_SELF_VERIFICATION)
9644/*
9645 * Save PC and registers to shadow memory for self verification mode
9646 * before jumping to native translation.
9647 * On entry:
9648 *    rPC, rFP, rGLUE: the values that they should contain
9649 *    r10: the address of the target translation.
9650 */
9651jitSVShadowRunStart:
9652    mov     r0,rPC                      @ r0<- program counter
9653    mov     r1,rFP                      @ r1<- frame pointer
9654    mov     r2,rGLUE                    @ r2<- InterpState pointer
9655    mov     r3,r10                      @ r3<- target translation
9656    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9657    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9658    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9659    bx      r10                         @ jump to the translation
9660
9661/*
9662 * Restore PC, registers, and interpState to original values
9663 * before jumping back to the interpreter.
9664 */
9665jitSVShadowRunEnd:
9666    mov    r1,rFP                        @ pass ending fp
9667    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9668    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9669    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9670    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9671    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9672    cmp    r1,#0                         @ check for punt condition
9673    beq    1f
9674    mov    r2,#kJitSelfVerification      @ ask for self verification
9675    str    r2,[rGLUE,#offGlue_jitState]
9676    mov    r2,#kInterpEntryInstr         @ normal entry reason
9677    str    r2,[rGLUE,#offGlue_entryPoint]
9678    mov    r1,#1                         @ set changeInterp
9679    b      common_gotoBail
9680
96811:                                       @ exit to interpreter without check
9682    EXPORT_PC()
9683    adrl   rIBASE, dvmAsmInstructionStart
9684    FETCH_INST()
9685    GET_INST_OPCODE(ip)
9686    GOTO_OPCODE(ip)
9687#endif
9688
9689#endif
9690
9691/*
9692 * Common code when a backward branch is taken.
9693 *
9694 * TODO: we could avoid a branch by just setting r0 and falling through
9695 * into the common_periodicChecks code, and having a test on r0 at the
9696 * end determine if we should return to the caller or update & branch to
9697 * the next instr.
9698 *
9699 * On entry:
9700 *  r9 is PC adjustment *in bytes*
9701 */
9702common_backwardBranch:
9703    mov     r0, #kInterpEntryInstr
9704    bl      common_periodicChecks
9705#if defined(WITH_JIT)
9706    GET_JIT_PROF_TABLE(r0)
9707    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9708    cmp     r0,#0
9709    bne     common_updateProfile
9710    GET_INST_OPCODE(ip)
9711    GOTO_OPCODE(ip)
9712#else
9713    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9714    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9715    GOTO_OPCODE(ip)                     @ jump to next instruction
9716#endif
9717
9718
9719/*
9720 * Need to see if the thread needs to be suspended or debugger/profiler
9721 * activity has begun.  If so, we suspend the thread or side-exit to
9722 * the debug interpreter as appropriate.
9723 *
9724 * The common case is no activity on any of these, so we want to figure
9725 * that out quickly.  If something is up, we can then sort out what.
9726 *
9727 * We want to be fast if the VM was built without debugger or profiler
9728 * support, but we also need to recognize that the system is usually
9729 * shipped with both of these enabled.
9730 *
9731 * TODO: reduce this so we're just checking a single location.
9732 *
9733 * On entry:
9734 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9735 *  r9 is trampoline PC adjustment *in bytes*
9736 */
9737common_periodicChecks:
9738    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9739
9740    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9741    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9742
9743    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9744
9745    cmp     r1, #0                      @ debugger enabled?
9746    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9747    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9748    orrnes  ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9749    /*
9750     * Don't switch the interpreter in the libdvm_traceview build even if the
9751     * profiler is active.
9752     * The code here is opted for less intrusion instead of performance.
9753     * That is, *pActiveProfilers is still loaded into r2 even though it is not
9754     * used when WITH_INLINE_PROFILING is defined.
9755     */
9756#if !defined(WITH_INLINE_PROFILING)
9757    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9758#endif
9759
9760
9761    bxeq    lr                          @ all zero, return
9762
9763    /*
9764     * One or more interesting events have happened.  Figure out what.
9765     *
9766     * If debugging or profiling are compiled in, we need to disambiguate.
9767     *
9768     * r0 still holds the reentry type.
9769     */
9770    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9771    cmp     ip, #0                      @ want suspend?
9772    beq     1f                          @ no, must be debugger/profiler
9773
9774    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9775#if defined(WITH_JIT)
9776    /*
9777     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9778     * doubles as the Jit's on/off switch.
9779     */
9780    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9781    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9782    ldr     r3, [r3] @ r3 <- pJitProfTable
9783    EXPORT_PC()                         @ need for precise GC
9784    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9785#else
9786    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9787    EXPORT_PC()                         @ need for precise GC
9788#endif
9789    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9790    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9791
9792    /*
9793     * Reload the debugger/profiler enable flags.  We're checking to see
9794     * if either of these got set while we were suspended.
9795     *
9796     * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9797     * is enabled or not as the profiling will be done inline.
9798     */
9799    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9800    cmp     r1, #0                      @ debugger enabled?
9801    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9802
9803#if !defined(WITH_INLINE_PROFILING)
9804    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9805    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9806    orrs    r1, r1, r2
9807#else
9808    cmp     r1, #0                      @ only consult the debuggerActive flag
9809#endif
9810
9811    beq     2f
9812
98131:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9814    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9815    add     rPC, rPC, r9                @ update rPC
9816    mov     r1, #1                      @ "want switch" = true
9817    b       common_gotoBail             @ side exit
9818
98192:
9820    bx      lr                          @ nothing to do, return
9821
9822
9823/*
9824 * The equivalent of "goto bail", this calls through the "bail handler".
9825 *
9826 * State registers will be saved to the "glue" area before bailing.
9827 *
9828 * On entry:
9829 *  r1 is "bool changeInterp", indicating if we want to switch to the
9830 *     other interpreter or just bail all the way out
9831 */
9832common_gotoBail:
9833    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9834    mov     r0, rGLUE                   @ r0<- glue ptr
9835    b       dvmMterpStdBail             @ call(glue, changeInterp)
9836
9837    @add     r1, r1, #1                  @ using (boolean+1)
9838    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9839    @bl      _longjmp                    @ does not return
9840    @bl      common_abort
9841
9842
9843/*
9844 * Common code for method invocation with range.
9845 *
9846 * On entry:
9847 *  r0 is "Method* methodToCall", the method we're trying to call
9848 */
9849common_invokeMethodRange:
9850.LinvokeNewRange:
9851    @ prepare to copy args to "outs" area of current frame
9852    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9853    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9854    beq     .LinvokeArgsDone            @ if no args, skip the rest
9855    FETCH(r1, 2)                        @ r1<- CCCC
9856
9857    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9858    @ (very few methods have > 10 args; could unroll for common cases)
9859    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9860    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9861    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
98621:  ldr     r1, [r3], #4                @ val = *fp++
9863    subs    r2, r2, #1                  @ count--
9864    str     r1, [r10], #4               @ *outs++ = val
9865    bne     1b                          @ ...while count != 0
9866    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9867    b       .LinvokeArgsDone
9868
9869/*
9870 * Common code for method invocation without range.
9871 *
9872 * On entry:
9873 *  r0 is "Method* methodToCall", the method we're trying to call
9874 */
9875common_invokeMethodNoRange:
9876.LinvokeNewNoRange:
9877    @ prepare to copy args to "outs" area of current frame
9878    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9879    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9880    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9881    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9882    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9883    beq     .LinvokeArgsDone
9884
9885    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9886.LinvokeNonRange:
9887    rsb     r2, r2, #5                  @ r2<- 5-r2
9888    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9889    bl      common_abort                @ (skipped due to ARM prefetch)
98905:  and     ip, rINST, #0x0f00          @ isolate A
9891    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9892    mov     r0, r0                      @ nop
9893    str     r2, [r10, #-4]!             @ *--outs = vA
98944:  and     ip, r1, #0xf000             @ isolate G
9895    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9896    mov     r0, r0                      @ nop
9897    str     r2, [r10, #-4]!             @ *--outs = vG
98983:  and     ip, r1, #0x0f00             @ isolate F
9899    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9900    mov     r0, r0                      @ nop
9901    str     r2, [r10, #-4]!             @ *--outs = vF
99022:  and     ip, r1, #0x00f0             @ isolate E
9903    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9904    mov     r0, r0                      @ nop
9905    str     r2, [r10, #-4]!             @ *--outs = vE
99061:  and     ip, r1, #0x000f             @ isolate D
9907    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9908    mov     r0, r0                      @ nop
9909    str     r2, [r10, #-4]!             @ *--outs = vD
99100:  @ fall through to .LinvokeArgsDone
9911
9912.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9913    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9914    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9915    @ find space for the new stack frame, check for overflow
9916    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9917    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9918    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9919@    bl      common_dumpRegs
9920    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9921    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9922    cmp     r3, r9                      @ bottom < interpStackEnd?
9923    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9924    blo     .LstackOverflow             @ yes, this frame will overflow stack
9925
9926    @ set up newSaveArea
9927#ifdef EASY_GDB
9928    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9929    str     ip, [r10, #offStackSaveArea_prevSave]
9930#endif
9931    str     rFP, [r10, #offStackSaveArea_prevFrame]
9932    str     rPC, [r10, #offStackSaveArea_savedPc]
9933#if defined(WITH_JIT)
9934    mov     r9, #0
9935    str     r9, [r10, #offStackSaveArea_returnAddr]
9936#endif
9937#if defined(WITH_INLINE_PROFILING)
9938    stmfd   sp!, {r0-r3}                @ preserve r0-r3
9939    mov     r1, r6
9940    @ r0=methodToCall, r1=rGlue
9941    bl      dvmFastMethodTraceEnter
9942    ldmfd   sp!, {r0-r3}                @ restore r0-r3
9943#endif
9944    str     r0, [r10, #offStackSaveArea_method]
9945    tst     r3, #ACC_NATIVE
9946    bne     .LinvokeNative
9947
9948    /*
9949    stmfd   sp!, {r0-r3}
9950    bl      common_printNewline
9951    mov     r0, rFP
9952    mov     r1, #0
9953    bl      dvmDumpFp
9954    ldmfd   sp!, {r0-r3}
9955    stmfd   sp!, {r0-r3}
9956    mov     r0, r1
9957    mov     r1, r10
9958    bl      dvmDumpFp
9959    bl      common_printNewline
9960    ldmfd   sp!, {r0-r3}
9961    */
9962
9963    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9964    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9965    mov     rPC, r2                         @ publish new rPC
9966    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9967
9968    @ Update "glue" values for the new method
9969    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9970    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9971    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
9972#if defined(WITH_JIT)
9973    GET_JIT_PROF_TABLE(r0)
9974    mov     rFP, r1                         @ fp = newFp
9975    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9976    mov     rINST, r9                       @ publish new rINST
9977    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9978    cmp     r0,#0
9979    bne     common_updateProfile
9980    GOTO_OPCODE(ip)                         @ jump to next instruction
9981#else
9982    mov     rFP, r1                         @ fp = newFp
9983    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
9984    mov     rINST, r9                       @ publish new rINST
9985    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
9986    GOTO_OPCODE(ip)                         @ jump to next instruction
9987#endif
9988
9989.LinvokeNative:
9990    @ Prep for the native call
9991    @ r0=methodToCall, r1=newFp, r10=newSaveArea
9992    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
9993    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
9994    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
9995    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
9996    mov     r9, r3                      @ r9<- glue->self (preserve)
9997
9998    mov     r2, r0                      @ r2<- methodToCall
9999    mov     r0, r1                      @ r0<- newFp (points to args)
10000    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10001
10002#ifdef ASSIST_DEBUGGER
10003    /* insert fake function header to help gdb find the stack frame */
10004    b       .Lskip
10005    .type   dalvik_mterp, %function
10006dalvik_mterp:
10007    .fnstart
10008    MTERP_ENTRY1
10009    MTERP_ENTRY2
10010.Lskip:
10011#endif
10012
10013#if defined(WITH_INLINE_PROFILING)
10014    @ r2=JNIMethod, r6=rGLUE
10015    stmfd   sp!, {r2,r6}
10016#endif
10017
10018    mov     lr, pc                      @ set return addr
10019    ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10020
10021#if defined(WITH_INLINE_PROFILING)
10022    @ r0=JNIMethod, r1=rGLUE
10023    ldmfd   sp!, {r0-r1}
10024    bl      dvmFastNativeMethodTraceExit
10025#endif
10026
10027#if defined(WITH_JIT)
10028    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10029#endif
10030
10031    @ native return; r9=self, r10=newSaveArea
10032    @ equivalent to dvmPopJniLocals
10033    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10034    ldr     r1, [r9, #offThread_exception] @ check for exception
10035#if defined(WITH_JIT)
10036    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10037#endif
10038    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10039    cmp     r1, #0                      @ null?
10040    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10041#if defined(WITH_JIT)
10042    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10043#endif
10044    bne     common_exceptionThrown      @ no, handle exception
10045
10046    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10047    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10048    GOTO_OPCODE(ip)                     @ jump to next instruction
10049
10050.LstackOverflow:    @ r0=methodToCall
10051    mov     r1, r0                      @ r1<- methodToCall
10052    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10053    bl      dvmHandleStackOverflow
10054    b       common_exceptionThrown
10055#ifdef ASSIST_DEBUGGER
10056    .fnend
10057#endif
10058
10059
10060    /*
10061     * Common code for method invocation, calling through "glue code".
10062     *
10063     * TODO: now that we have range and non-range invoke handlers, this
10064     *       needs to be split into two.  Maybe just create entry points
10065     *       that set r9 and jump here?
10066     *
10067     * On entry:
10068     *  r0 is "Method* methodToCall", the method we're trying to call
10069     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10070     */
10071     .if    0
10072.LinvokeOld:
10073    sub     sp, sp, #8                  @ space for args + pad
10074    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10075    mov     r2, r0                      @ A2<- methodToCall
10076    mov     r0, rGLUE                   @ A0<- glue
10077    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10078    mov     r1, r9                      @ A1<- methodCallRange
10079    mov     r3, rINST, lsr #8           @ A3<- AA
10080    str     ip, [sp, #0]                @ A4<- ip
10081    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10082    add     sp, sp, #8                  @ remove arg area
10083    b       common_resumeAfterGlueCall  @ continue to next instruction
10084    .endif
10085
10086
10087
10088/*
10089 * Common code for handling a return instruction.
10090 *
10091 * This does not return.
10092 */
10093common_returnFromMethod:
10094.LreturnNew:
10095    mov     r0, #kInterpEntryReturn
10096    mov     r9, #0
10097    bl      common_periodicChecks
10098
10099#if defined(WITH_INLINE_PROFILING)
10100    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10101    mov     r0, r6
10102    @ r0=rGlue
10103    bl      dvmFastJavaMethodTraceExit
10104    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10105#endif
10106    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10107    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10108    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10109    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10110                                        @ r2<- method we're returning to
10111    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10112    cmp     r2, #0                      @ is this a break frame?
10113    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10114    mov     r1, #0                      @ "want switch" = false
10115    beq     common_gotoBail             @ break frame, bail out completely
10116
10117    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10118    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10119    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10120    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10121#if defined(WITH_JIT)
10122    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10123    mov     rPC, r9                     @ publish new rPC
10124    str     r1, [rGLUE, #offGlue_methodClassDex]
10125    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10126    cmp     r10, #0                      @ caller is compiled code
10127    blxne   r10
10128    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10129    GOTO_OPCODE(ip)                     @ jump to next instruction
10130#else
10131    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10132    mov     rPC, r9                     @ publish new rPC
10133    str     r1, [rGLUE, #offGlue_methodClassDex]
10134    GOTO_OPCODE(ip)                     @ jump to next instruction
10135#endif
10136
10137    /*
10138     * Return handling, calls through "glue code".
10139     */
10140     .if    0
10141.LreturnOld:
10142    SAVE_PC_FP_TO_GLUE()                @ export state
10143    mov     r0, rGLUE                   @ arg to function
10144    bl      dvmMterp_returnFromMethod
10145    b       common_resumeAfterGlueCall
10146    .endif
10147
10148
10149/*
10150 * Somebody has thrown an exception.  Handle it.
10151 *
10152 * If the exception processing code returns to us (instead of falling
10153 * out of the interpreter), continue with whatever the next instruction
10154 * now happens to be.
10155 *
10156 * This does not return.
10157 */
10158     .global dvmMterpCommonExceptionThrown
10159dvmMterpCommonExceptionThrown:
10160common_exceptionThrown:
10161.LexceptionNew:
10162    mov     r0, #kInterpEntryThrow
10163    mov     r9, #0
10164    bl      common_periodicChecks
10165
10166    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10167    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10168    mov     r1, r10                     @ r1<- self
10169    mov     r0, r9                      @ r0<- exception
10170    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10171    mov     r3, #0                      @ r3<- NULL
10172    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10173
10174    /* set up args and a local for "&fp" */
10175    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10176    str     rFP, [sp, #-4]!             @ *--sp = fp
10177    mov     ip, sp                      @ ip<- &fp
10178    mov     r3, #0                      @ r3<- false
10179    str     ip, [sp, #-4]!              @ *--sp = &fp
10180    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10181    mov     r0, r10                     @ r0<- self
10182    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10183    mov     r2, r9                      @ r2<- exception
10184    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10185    mov     r1, r1, asr #1              @ r1<- offset in code units
10186
10187    /* call, r0 gets catchRelPc (a code-unit offset) */
10188    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10189
10190    /* fix earlier stack overflow if necessary; may trash rFP */
10191    ldrb    r1, [r10, #offThread_stackOverflowed]
10192    cmp     r1, #0                      @ did we overflow earlier?
10193    beq     1f                          @ no, skip ahead
10194    mov     rFP, r0                     @ save relPc result in rFP
10195    mov     r0, r10                     @ r0<- self
10196    mov     r1, r9                      @ r1<- exception
10197    bl      dvmCleanupStackOverflow     @ call(self)
10198    mov     r0, rFP                     @ restore result
101991:
10200
10201    /* update frame pointer and check result from dvmFindCatchBlock */
10202    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10203    cmp     r0, #0                      @ is catchRelPc < 0?
10204    add     sp, sp, #8                  @ restore stack
10205    bmi     .LnotCaughtLocally
10206
10207    /* adjust locals to match self->curFrame and updated PC */
10208    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10209    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10210    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10211    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10212    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10213    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10214    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10215    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10216
10217    /* release the tracked alloc on the exception */
10218    mov     r0, r9                      @ r0<- exception
10219    mov     r1, r10                     @ r1<- self
10220    bl      dvmReleaseTrackedAlloc      @ release the exception
10221
10222    /* restore the exception if the handler wants it */
10223    FETCH_INST()                        @ load rINST from rPC
10224    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10225    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10226    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10227    GOTO_OPCODE(ip)                     @ jump to next instruction
10228
10229.LnotCaughtLocally: @ r9=exception, r10=self
10230    /* fix stack overflow if necessary */
10231    ldrb    r1, [r10, #offThread_stackOverflowed]
10232    cmp     r1, #0                      @ did we overflow earlier?
10233    movne   r0, r10                     @ if yes: r0<- self
10234    movne   r1, r9                      @ if yes: r1<- exception
10235    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10236
10237    @ may want to show "not caught locally" debug messages here
10238#if DVM_SHOW_EXCEPTION >= 2
10239    /* call __android_log_print(prio, tag, format, ...) */
10240    /* "Exception %s from %s:%d not caught locally" */
10241    @ dvmLineNumFromPC(method, pc - method->insns)
10242    ldr     r0, [rGLUE, #offGlue_method]
10243    ldr     r1, [r0, #offMethod_insns]
10244    sub     r1, rPC, r1
10245    asr     r1, r1, #1
10246    bl      dvmLineNumFromPC
10247    str     r0, [sp, #-4]!
10248    @ dvmGetMethodSourceFile(method)
10249    ldr     r0, [rGLUE, #offGlue_method]
10250    bl      dvmGetMethodSourceFile
10251    str     r0, [sp, #-4]!
10252    @ exception->clazz->descriptor
10253    ldr     r3, [r9, #offObject_clazz]
10254    ldr     r3, [r3, #offClassObject_descriptor]
10255    @
10256    ldr     r2, strExceptionNotCaughtLocally
10257    ldr     r1, strLogTag
10258    mov     r0, #3                      @ LOG_DEBUG
10259    bl      __android_log_print
10260#endif
10261    str     r9, [r10, #offThread_exception] @ restore exception
10262    mov     r0, r9                      @ r0<- exception
10263    mov     r1, r10                     @ r1<- self
10264    bl      dvmReleaseTrackedAlloc      @ release the exception
10265    mov     r1, #0                      @ "want switch" = false
10266    b       common_gotoBail             @ bail out
10267
10268
10269    /*
10270     * Exception handling, calls through "glue code".
10271     */
10272    .if     0
10273.LexceptionOld:
10274    SAVE_PC_FP_TO_GLUE()                @ export state
10275    mov     r0, rGLUE                   @ arg to function
10276    bl      dvmMterp_exceptionThrown
10277    b       common_resumeAfterGlueCall
10278    .endif
10279
10280
10281/*
10282 * After returning from a "glued" function, pull out the updated
10283 * values and start executing at the next instruction.
10284 */
10285common_resumeAfterGlueCall:
10286    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10287    FETCH_INST()                        @ load rINST from rPC
10288    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10289    GOTO_OPCODE(ip)                     @ jump to next instruction
10290
10291/*
10292 * Invalid array index. Note that our calling convention is strange; we use r1
10293 * and r3 because those just happen to be the registers all our callers are
10294 * using. We shuffle them here before calling the C function.
10295 * r1: index
10296 * r3: size
10297 */
10298common_errArrayIndex:
10299    EXPORT_PC()
10300    mov     r0, r1
10301    mov     r1, r3
10302    bl      dvmThrowAIOOBE
10303    b       common_exceptionThrown
10304
10305/*
10306 * Invalid array value.
10307 */
10308common_errArrayStore:
10309    EXPORT_PC()
10310    ldr     r0, strArrayStoreException
10311    mov     r1, #0
10312    bl      dvmThrowException
10313    b       common_exceptionThrown
10314
10315/*
10316 * Integer divide or mod by zero.
10317 */
10318common_errDivideByZero:
10319    EXPORT_PC()
10320    ldr     r0, strArithmeticException
10321    ldr     r1, strDivideByZero
10322    bl      dvmThrowException
10323    b       common_exceptionThrown
10324
10325/*
10326 * Attempt to allocate an array with a negative size.
10327 */
10328common_errNegativeArraySize:
10329    EXPORT_PC()
10330    ldr     r0, strNegativeArraySizeException
10331    mov     r1, #0
10332    bl      dvmThrowException
10333    b       common_exceptionThrown
10334
10335/*
10336 * Invocation of a non-existent method.
10337 */
10338common_errNoSuchMethod:
10339    EXPORT_PC()
10340    ldr     r0, strNoSuchMethodError
10341    mov     r1, #0
10342    bl      dvmThrowException
10343    b       common_exceptionThrown
10344
10345/*
10346 * We encountered a null object when we weren't expecting one.  We
10347 * export the PC, throw a NullPointerException, and goto the exception
10348 * processing code.
10349 */
10350common_errNullObject:
10351    EXPORT_PC()
10352    ldr     r0, strNullPointerException
10353    mov     r1, #0
10354    bl      dvmThrowException
10355    b       common_exceptionThrown
10356
10357/*
10358 * For debugging, cause an immediate fault.  The source address will
10359 * be in lr (use a bl instruction to jump here).
10360 */
10361common_abort:
10362    ldr     pc, .LdeadFood
10363.LdeadFood:
10364    .word   0xdeadf00d
10365
10366/*
10367 * Spit out a "we were here", preserving all registers.  (The attempt
10368 * to save ip won't work, but we need to save an even number of
10369 * registers for EABI 64-bit stack alignment.)
10370 */
10371    .macro  SQUEAK num
10372common_squeak\num:
10373    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10374    ldr     r0, strSqueak
10375    mov     r1, #\num
10376    bl      printf
10377    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10378    bx      lr
10379    .endm
10380
10381    SQUEAK  0
10382    SQUEAK  1
10383    SQUEAK  2
10384    SQUEAK  3
10385    SQUEAK  4
10386    SQUEAK  5
10387
10388/*
10389 * Spit out the number in r0, preserving registers.
10390 */
10391common_printNum:
10392    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10393    mov     r1, r0
10394    ldr     r0, strSqueak
10395    bl      printf
10396    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10397    bx      lr
10398
10399/*
10400 * Print a newline, preserving registers.
10401 */
10402common_printNewline:
10403    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10404    ldr     r0, strNewline
10405    bl      printf
10406    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10407    bx      lr
10408
10409    /*
10410     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10411     */
10412common_printHex:
10413    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10414    mov     r1, r0
10415    ldr     r0, strPrintHex
10416    bl      printf
10417    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10418    bx      lr
10419
10420/*
10421 * Print the 64-bit quantity in r0-r1, preserving registers.
10422 */
10423common_printLong:
10424    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10425    mov     r3, r1
10426    mov     r2, r0
10427    ldr     r0, strPrintLong
10428    bl      printf
10429    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10430    bx      lr
10431
10432/*
10433 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10434 */
10435common_printMethod:
10436    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10437    bl      dvmMterpPrintMethod
10438    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10439    bx      lr
10440
10441/*
10442 * Call a C helper function that dumps regs and possibly some
10443 * additional info.  Requires the C function to be compiled in.
10444 */
10445    .if     0
10446common_dumpRegs:
10447    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10448    bl      dvmMterpDumpArmRegs
10449    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10450    bx      lr
10451    .endif
10452
10453#if 0
10454/*
10455 * Experiment on VFP mode.
10456 *
10457 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10458 *
10459 * Updates the bits specified by "mask", setting them to the values in "val".
10460 */
10461setFPSCR:
10462    and     r0, r0, r1                  @ make sure no stray bits are set
10463    fmrx    r2, fpscr                   @ get VFP reg
10464    mvn     r1, r1                      @ bit-invert mask
10465    and     r2, r2, r1                  @ clear masked bits
10466    orr     r2, r2, r0                  @ set specified bits
10467    fmxr    fpscr, r2                   @ set VFP reg
10468    mov     r0, r2                      @ return new value
10469    bx      lr
10470
10471    .align  2
10472    .global dvmConfigureFP
10473    .type   dvmConfigureFP, %function
10474dvmConfigureFP:
10475    stmfd   sp!, {ip, lr}
10476    /* 0x03000000 sets DN/FZ */
10477    /* 0x00009f00 clears the six exception enable flags */
10478    bl      common_squeak0
10479    mov     r0, #0x03000000             @ r0<- 0x03000000
10480    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10481    bl      setFPSCR
10482    ldmfd   sp!, {ip, pc}
10483#endif
10484
10485
10486/*
10487 * String references, must be close to the code that uses them.
10488 */
10489    .align  2
10490strArithmeticException:
10491    .word   .LstrArithmeticException
10492strArrayStoreException:
10493    .word   .LstrArrayStoreException
10494strDivideByZero:
10495    .word   .LstrDivideByZero
10496strNegativeArraySizeException:
10497    .word   .LstrNegativeArraySizeException
10498strNoSuchMethodError:
10499    .word   .LstrNoSuchMethodError
10500strNullPointerException:
10501    .word   .LstrNullPointerException
10502
10503strLogTag:
10504    .word   .LstrLogTag
10505strExceptionNotCaughtLocally:
10506    .word   .LstrExceptionNotCaughtLocally
10507
10508strNewline:
10509    .word   .LstrNewline
10510strSqueak:
10511    .word   .LstrSqueak
10512strPrintHex:
10513    .word   .LstrPrintHex
10514strPrintLong:
10515    .word   .LstrPrintLong
10516
10517/*
10518 * Zero-terminated ASCII string data.
10519 *
10520 * On ARM we have two choices: do like gcc does, and LDR from a .word
10521 * with the address, or use an ADR pseudo-op to get the address
10522 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10523 * PC-relative addressing mode and hence has a limited range, which
10524 * makes it not work well with mergeable string sections.
10525 */
10526    .section .rodata.str1.4,"aMS",%progbits,1
10527
10528.LstrBadEntryPoint:
10529    .asciz  "Bad entry point %d\n"
10530.LstrArithmeticException:
10531    .asciz  "Ljava/lang/ArithmeticException;"
10532.LstrArrayStoreException:
10533    .asciz  "Ljava/lang/ArrayStoreException;"
10534.LstrClassCastException:
10535    .asciz  "Ljava/lang/ClassCastException;"
10536.LstrDivideByZero:
10537    .asciz  "divide by zero"
10538.LstrFilledNewArrayNotImpl:
10539    .asciz  "filled-new-array only implemented for objects and 'int'"
10540.LstrInternalError:
10541    .asciz  "Ljava/lang/InternalError;"
10542.LstrInstantiationError:
10543    .asciz  "Ljava/lang/InstantiationError;"
10544.LstrNegativeArraySizeException:
10545    .asciz  "Ljava/lang/NegativeArraySizeException;"
10546.LstrNoSuchMethodError:
10547    .asciz  "Ljava/lang/NoSuchMethodError;"
10548.LstrNullPointerException:
10549    .asciz  "Ljava/lang/NullPointerException;"
10550
10551.LstrLogTag:
10552    .asciz  "mterp"
10553.LstrExceptionNotCaughtLocally:
10554    .asciz  "Exception %s from %s:%d not caught locally\n"
10555
10556.LstrNewline:
10557    .asciz  "\n"
10558.LstrSqueak:
10559    .asciz  "<%d>"
10560.LstrPrintHex:
10561    .asciz  "<0x%x>"
10562.LstrPrintLong:
10563    .asciz  "<%lld>"
10564
10565