InterpAsm-armv5te-vfp.S revision c35a2ef53d0cccd6f924eeba36633220ec67c32e
1/*
2 * This file was generated automatically by gen-mterp.py for 'armv5te-vfp'.
3 *
4 * --> DO NOT EDIT <--
5 */
6
7/* File: armv5te/header.S */
8/*
9 * Copyright (C) 2008 The Android Open Source Project
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 *      http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/*
25 * ARMv5 definitions and declarations.
26 */
27
28/*
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: armv5te/platform.S */
210/*
211 * ===========================================================================
212 *  CPU-version-specific defines
213 * ===========================================================================
214 */
215
216/*
217 * Macro for "LDR PC,xxx", which is not allowed pre-ARMv5.  Essentially a
218 * one-way branch.
219 *
220 * May modify IP.  Does not modify LR.
221 */
222.macro  LDR_PC source
223    ldr     pc, \source
224.endm
225
226/*
227 * Macro for "MOV LR,PC / LDR PC,xxx", which is not allowed pre-ARMv5.
228 * Jump to subroutine.
229 *
230 * May modify IP and LR.
231 */
232.macro  LDR_PC_LR source
233    mov     lr, pc
234    ldr     pc, \source
235.endm
236
237/*
238 * Macro for "LDMFD SP!, {...regs...,PC}".
239 *
240 * May modify IP and LR.
241 */
242.macro  LDMFD_PC regs
243    ldmfd   sp!, {\regs,pc}
244.endm
245
246/*
247 * Macro for data memory barrier; not meaningful pre-ARMv6K.
248 */
249.macro  SMP_DMB gen
250.endm
251
252
253/* File: armv5te/entry.S */
254/*
255 * Copyright (C) 2008 The Android Open Source Project
256 *
257 * Licensed under the Apache License, Version 2.0 (the "License");
258 * you may not use this file except in compliance with the License.
259 * You may obtain a copy of the License at
260 *
261 *      http://www.apache.org/licenses/LICENSE-2.0
262 *
263 * Unless required by applicable law or agreed to in writing, software
264 * distributed under the License is distributed on an "AS IS" BASIS,
265 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
266 * See the License for the specific language governing permissions and
267 * limitations under the License.
268 */
269/*
270 * Interpreter entry point.
271 */
272
273/*
274 * We don't have formal stack frames, so gdb scans upward in the code
275 * to find the start of the function (a label with the %function type),
276 * and then looks at the next few instructions to figure out what
277 * got pushed onto the stack.  From this it figures out how to restore
278 * the registers, including PC, for the previous stack frame.  If gdb
279 * sees a non-function label, it stops scanning, so either we need to
280 * have nothing but assembler-local labels between the entry point and
281 * the break, or we need to fake it out.
282 *
283 * When this is defined, we add some stuff to make gdb less confused.
284 */
285#define ASSIST_DEBUGGER 1
286
287    .text
288    .align  2
289    .global dvmMterpStdRun
290    .type   dvmMterpStdRun, %function
291
292/*
293 * On entry:
294 *  r0  MterpGlue* glue
295 *
296 * This function returns a boolean "changeInterp" value.  The return comes
297 * via a call to dvmMterpStdBail().
298 */
299dvmMterpStdRun:
300#define MTERP_ENTRY1 \
301    .save {r4-r10,fp,lr}; \
302    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
303#define MTERP_ENTRY2 \
304    .pad    #4; \
305    sub     sp, sp, #4                  @ align 64
306
307    .fnstart
308    MTERP_ENTRY1
309    MTERP_ENTRY2
310
311    /* save stack pointer, add magic word for debuggerd */
312    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
313
314    /* set up "named" registers, figure out entry point */
315    mov     rGLUE, r0                   @ set rGLUE
316    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
317    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
318    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
319    cmp     r1, #kInterpEntryInstr      @ usual case?
320    bne     .Lnot_instr                 @ no, handle it
321
322#if defined(WITH_JIT)
323.LentryInstr:
324    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
325    /* Entry is always a possible trace start */
326    GET_JIT_PROF_TABLE(r0)
327    FETCH_INST()
328    mov    r1, #0                       @ prepare the value for the new state
329    str    r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
330    cmp    r0,#0
331    bne    common_updateProfile
332    GET_INST_OPCODE(ip)
333    GOTO_OPCODE(ip)
334#else
335    /* start executing the instruction at rPC */
336    FETCH_INST()                        @ load rINST from rPC
337    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
338    GOTO_OPCODE(ip)                     @ jump to next instruction
339#endif
340
341.Lnot_instr:
342    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
343    beq     common_returnFromMethod
344
345.Lnot_return:
346    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
347    beq     common_exceptionThrown
348
349#if defined(WITH_JIT)
350.Lnot_throw:
351    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
352    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
353    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
354    bne     .Lbad_arg
355    cmp     rPC,r2
356    bne     .LentryInstr                @ must have branched, don't resume
357#if defined(WITH_SELF_VERIFICATION)
358    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
359    b       jitSVShadowRunStart         @ re-enter the translation after the
360                                        @ single-stepped instruction
361    @noreturn
362#endif
363    mov     r1, #kInterpEntryInstr
364    str     r1, [rGLUE, #offGlue_entryPoint]
365    bx      r10                         @ re-enter the translation
366#endif
367
368.Lbad_arg:
369    ldr     r0, strBadEntryPoint
370    @ r1 holds value of entryPoint
371    bl      printf
372    bl      dvmAbort
373    .fnend
374
375
376    .global dvmMterpStdBail
377    .type   dvmMterpStdBail, %function
378
379/*
380 * Restore the stack pointer and PC from the save point established on entry.
381 * This is essentially the same as a longjmp, but should be cheaper.  The
382 * last instruction causes us to return to whoever called dvmMterpStdRun.
383 *
384 * We pushed some registers on the stack in dvmMterpStdRun, then saved
385 * SP and LR.  Here we restore SP, restore the registers, and then restore
386 * LR to PC.
387 *
388 * On entry:
389 *  r0  MterpGlue* glue
390 *  r1  bool changeInterp
391 */
392dvmMterpStdBail:
393    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
394    mov     r0, r1                          @ return the changeInterp value
395    add     sp, sp, #4                      @ un-align 64
396    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
397
398
399/*
400 * String references.
401 */
402strBadEntryPoint:
403    .word   .LstrBadEntryPoint
404
405
406    .global dvmAsmInstructionStart
407    .type   dvmAsmInstructionStart, %function
408dvmAsmInstructionStart = .L_OP_NOP
409    .text
410
411/* ------------------------------ */
412    .balign 64
413.L_OP_NOP: /* 0x00 */
414/* File: armv5te/OP_NOP.S */
415    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
416    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
417    GOTO_OPCODE(ip)                     @ execute it
418
419#ifdef ASSIST_DEBUGGER
420    /* insert fake function header to help gdb find the stack frame */
421    .type   dalvik_inst, %function
422dalvik_inst:
423    .fnstart
424    MTERP_ENTRY1
425    MTERP_ENTRY2
426    .fnend
427#endif
428
429/* ------------------------------ */
430    .balign 64
431.L_OP_MOVE: /* 0x01 */
432/* File: armv5te/OP_MOVE.S */
433    /* for move, move-object, long-to-int */
434    /* op vA, vB */
435    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
436    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
437    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
438    GET_VREG(r2, r1)                    @ r2<- fp[B]
439    and     r0, r0, #15
440    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
441    SET_VREG(r2, r0)                    @ fp[A]<- r2
442    GOTO_OPCODE(ip)                     @ execute next instruction
443
444/* ------------------------------ */
445    .balign 64
446.L_OP_MOVE_FROM16: /* 0x02 */
447/* File: armv5te/OP_MOVE_FROM16.S */
448    /* for: move/from16, move-object/from16 */
449    /* op vAA, vBBBB */
450    FETCH(r1, 1)                        @ r1<- BBBB
451    mov     r0, rINST, lsr #8           @ r0<- AA
452    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
453    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
455    SET_VREG(r2, r0)                    @ fp[AA]<- r2
456    GOTO_OPCODE(ip)                     @ jump to next instruction
457
458/* ------------------------------ */
459    .balign 64
460.L_OP_MOVE_16: /* 0x03 */
461/* File: armv5te/OP_MOVE_16.S */
462    /* for: move/16, move-object/16 */
463    /* op vAAAA, vBBBB */
464    FETCH(r1, 2)                        @ r1<- BBBB
465    FETCH(r0, 1)                        @ r0<- AAAA
466    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
467    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
469    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
470    GOTO_OPCODE(ip)                     @ jump to next instruction
471
472/* ------------------------------ */
473    .balign 64
474.L_OP_MOVE_WIDE: /* 0x04 */
475/* File: armv5te/OP_MOVE_WIDE.S */
476    /* move-wide vA, vB */
477    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
478    mov     r2, rINST, lsr #8           @ r2<- A(+)
479    mov     r3, rINST, lsr #12          @ r3<- B
480    and     r2, r2, #15
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: armv5te/OP_CONST_4.S */
687    /* const/4 vA, #+B */
688    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
689    mov     r0, rINST, lsr #8           @ r0<- A+
690    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
691    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
692    and     r0, r0, #15
693    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
694    SET_VREG(r1, r0)                    @ fp[A]<- r1
695    GOTO_OPCODE(ip)                     @ execute next instruction
696
697/* ------------------------------ */
698    .balign 64
699.L_OP_CONST_16: /* 0x13 */
700/* File: armv5te/OP_CONST_16.S */
701    /* const/16 vAA, #+BBBB */
702    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
703    mov     r3, rINST, lsr #8           @ r3<- AA
704    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
705    SET_VREG(r0, r3)                    @ vAA<- r0
706    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
707    GOTO_OPCODE(ip)                     @ jump to next instruction
708
709/* ------------------------------ */
710    .balign 64
711.L_OP_CONST: /* 0x14 */
712/* File: armv5te/OP_CONST.S */
713    /* const vAA, #+BBBBbbbb */
714    mov     r3, rINST, lsr #8           @ r3<- AA
715    FETCH(r0, 1)                        @ r0<- bbbb (low)
716    FETCH(r1, 2)                        @ r1<- BBBB (high)
717    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
718    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
719    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
720    SET_VREG(r0, r3)                    @ vAA<- r0
721    GOTO_OPCODE(ip)                     @ jump to next instruction
722
723/* ------------------------------ */
724    .balign 64
725.L_OP_CONST_HIGH16: /* 0x15 */
726/* File: armv5te/OP_CONST_HIGH16.S */
727    /* const/high16 vAA, #+BBBB0000 */
728    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
729    mov     r3, rINST, lsr #8           @ r3<- AA
730    mov     r0, r0, lsl #16             @ r0<- BBBB0000
731    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
732    SET_VREG(r0, r3)                    @ vAA<- r0
733    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
734    GOTO_OPCODE(ip)                     @ jump to next instruction
735
736/* ------------------------------ */
737    .balign 64
738.L_OP_CONST_WIDE_16: /* 0x16 */
739/* File: armv5te/OP_CONST_WIDE_16.S */
740    /* const-wide/16 vAA, #+BBBB */
741    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
742    mov     r3, rINST, lsr #8           @ r3<- AA
743    mov     r1, r0, asr #31             @ r1<- ssssssss
744    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
745    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
746    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
747    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
748    GOTO_OPCODE(ip)                     @ jump to next instruction
749
750/* ------------------------------ */
751    .balign 64
752.L_OP_CONST_WIDE_32: /* 0x17 */
753/* File: armv5te/OP_CONST_WIDE_32.S */
754    /* const-wide/32 vAA, #+BBBBbbbb */
755    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
756    mov     r3, rINST, lsr #8           @ r3<- AA
757    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
758    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
759    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
760    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
761    mov     r1, r0, asr #31             @ r1<- ssssssss
762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
763    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
764    GOTO_OPCODE(ip)                     @ jump to next instruction
765
766/* ------------------------------ */
767    .balign 64
768.L_OP_CONST_WIDE: /* 0x18 */
769/* File: armv5te/OP_CONST_WIDE.S */
770    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
771    FETCH(r0, 1)                        @ r0<- bbbb (low)
772    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
773    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
774    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
775    FETCH(r3, 4)                        @ r3<- HHHH (high)
776    mov     r9, rINST, lsr #8           @ r9<- AA
777    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
778    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
779    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
781    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
782    GOTO_OPCODE(ip)                     @ jump to next instruction
783
784/* ------------------------------ */
785    .balign 64
786.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
787/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
788    /* const-wide/high16 vAA, #+BBBB000000000000 */
789    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
790    mov     r3, rINST, lsr #8           @ r3<- AA
791    mov     r0, #0                      @ r0<- 00000000
792    mov     r1, r1, lsl #16             @ r1<- BBBB0000
793    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
794    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
795    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
796    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
797    GOTO_OPCODE(ip)                     @ jump to next instruction
798
799/* ------------------------------ */
800    .balign 64
801.L_OP_CONST_STRING: /* 0x1a */
802/* File: armv5te/OP_CONST_STRING.S */
803    /* const/string vAA, String@BBBB */
804    FETCH(r1, 1)                        @ r1<- BBBB
805    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
806    mov     r9, rINST, lsr #8           @ r9<- AA
807    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
808    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
809    cmp     r0, #0                      @ not yet resolved?
810    beq     .LOP_CONST_STRING_resolve
811    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
813    SET_VREG(r0, r9)                    @ vAA<- r0
814    GOTO_OPCODE(ip)                     @ jump to next instruction
815
816/* ------------------------------ */
817    .balign 64
818.L_OP_CONST_STRING_JUMBO: /* 0x1b */
819/* File: armv5te/OP_CONST_STRING_JUMBO.S */
820    /* const/string vAA, String@BBBBBBBB */
821    FETCH(r0, 1)                        @ r0<- bbbb (low)
822    FETCH(r1, 2)                        @ r1<- BBBB (high)
823    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
824    mov     r9, rINST, lsr #8           @ r9<- AA
825    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
826    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
827    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
828    cmp     r0, #0
829    beq     .LOP_CONST_STRING_JUMBO_resolve
830    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
831    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
832    SET_VREG(r0, r9)                    @ vAA<- r0
833    GOTO_OPCODE(ip)                     @ jump to next instruction
834
835/* ------------------------------ */
836    .balign 64
837.L_OP_CONST_CLASS: /* 0x1c */
838/* File: armv5te/OP_CONST_CLASS.S */
839    /* const/class vAA, Class@BBBB */
840    FETCH(r1, 1)                        @ r1<- BBBB
841    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
842    mov     r9, rINST, lsr #8           @ r9<- AA
843    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
844    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
845    cmp     r0, #0                      @ not yet resolved?
846    beq     .LOP_CONST_CLASS_resolve
847    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
849    SET_VREG(r0, r9)                    @ vAA<- r0
850    GOTO_OPCODE(ip)                     @ jump to next instruction
851
852/* ------------------------------ */
853    .balign 64
854.L_OP_MONITOR_ENTER: /* 0x1d */
855/* File: armv5te/OP_MONITOR_ENTER.S */
856    /*
857     * Synchronize on an object.
858     */
859    /* monitor-enter vAA */
860    mov     r2, rINST, lsr #8           @ r2<- AA
861    GET_VREG(r1, r2)                    @ r1<- vAA (object)
862    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
863    cmp     r1, #0                      @ null object?
864    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
865    beq     common_errNullObject        @ null object, throw an exception
866    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
867    bl      dvmLockObject               @ call(self, obj)
868#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
869    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
870    ldr     r1, [r0, #offThread_exception] @ check for exception
871    cmp     r1, #0
872    bne     common_exceptionThrown      @ exception raised, bail out
873#endif
874    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
875    GOTO_OPCODE(ip)                     @ jump to next instruction
876
877/* ------------------------------ */
878    .balign 64
879.L_OP_MONITOR_EXIT: /* 0x1e */
880/* File: armv5te/OP_MONITOR_EXIT.S */
881    /*
882     * Unlock an object.
883     *
884     * Exceptions that occur when unlocking a monitor need to appear as
885     * if they happened at the following instruction.  See the Dalvik
886     * instruction spec.
887     */
888    /* monitor-exit vAA */
889    mov     r2, rINST, lsr #8           @ r2<- AA
890    EXPORT_PC()                         @ before fetch: export the PC
891    GET_VREG(r1, r2)                    @ r1<- vAA (object)
892    cmp     r1, #0                      @ null object?
893    beq     1f                          @ yes
894    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
895    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
896    cmp     r0, #0                      @ failed?
897    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
898    beq     common_exceptionThrown      @ yes, exception is pending
899    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
900    GOTO_OPCODE(ip)                     @ jump to next instruction
9011:
902    FETCH_ADVANCE_INST(1)               @ advance before throw
903    b      common_errNullObject
904
905/* ------------------------------ */
906    .balign 64
907.L_OP_CHECK_CAST: /* 0x1f */
908/* File: armv5te/OP_CHECK_CAST.S */
909    /*
910     * Check to see if a cast from one class to another is allowed.
911     */
912    /* check-cast vAA, class@BBBB */
913    mov     r3, rINST, lsr #8           @ r3<- AA
914    FETCH(r2, 1)                        @ r2<- BBBB
915    GET_VREG(r9, r3)                    @ r9<- object
916    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
917    cmp     r9, #0                      @ is object null?
918    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
919    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
920    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
921    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
922    cmp     r1, #0                      @ have we resolved this before?
923    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
924.LOP_CHECK_CAST_resolved:
925    cmp     r0, r1                      @ same class (trivial success)?
926    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
927.LOP_CHECK_CAST_okay:
928    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
929    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
930    GOTO_OPCODE(ip)                     @ jump to next instruction
931
932/* ------------------------------ */
933    .balign 64
934.L_OP_INSTANCE_OF: /* 0x20 */
935/* File: armv5te/OP_INSTANCE_OF.S */
936    /*
937     * Check to see if an object reference is an instance of a class.
938     *
939     * Most common situation is a non-null object, being compared against
940     * an already-resolved class.
941     */
942    /* instance-of vA, vB, class@CCCC */
943    mov     r3, rINST, lsr #12          @ r3<- B
944    mov     r9, rINST, lsr #8           @ r9<- A+
945    GET_VREG(r0, r3)                    @ r0<- vB (object)
946    and     r9, r9, #15                 @ r9<- A
947    cmp     r0, #0                      @ is object null?
948    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
949    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
950    FETCH(r3, 1)                        @ r3<- CCCC
951    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
952    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
953    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
954    cmp     r1, #0                      @ have we resolved this before?
955    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
956.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
957    cmp     r0, r1                      @ same class (trivial success)?
958    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
959    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
960
961/* ------------------------------ */
962    .balign 64
963.L_OP_ARRAY_LENGTH: /* 0x21 */
964/* File: armv5te/OP_ARRAY_LENGTH.S */
965    /*
966     * Return the length of an array.
967     */
968    mov     r1, rINST, lsr #12          @ r1<- B
969    mov     r2, rINST, lsr #8           @ r2<- A+
970    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
971    and     r2, r2, #15                 @ r2<- A
972    cmp     r0, #0                      @ is object null?
973    beq     common_errNullObject        @ yup, fail
974    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
975    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
976    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
977    SET_VREG(r3, r2)                    @ vB<- length
978    GOTO_OPCODE(ip)                     @ jump to next instruction
979
980/* ------------------------------ */
981    .balign 64
982.L_OP_NEW_INSTANCE: /* 0x22 */
983/* File: armv5te/OP_NEW_INSTANCE.S */
984    /*
985     * Create a new instance of a class.
986     */
987    /* new-instance vAA, class@BBBB */
988    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
989    FETCH(r1, 1)                        @ r1<- BBBB
990    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
991    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
992    EXPORT_PC()                         @ req'd for init, resolve, alloc
993    cmp     r0, #0                      @ already resolved?
994    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
995.LOP_NEW_INSTANCE_resolved:   @ r0=class
996    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
997    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
998    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
999.LOP_NEW_INSTANCE_initialized: @ r0=class
1000    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1001    bl      dvmAllocObject              @ r0<- new object
1002    b       .LOP_NEW_INSTANCE_finish          @ continue
1003
1004/* ------------------------------ */
1005    .balign 64
1006.L_OP_NEW_ARRAY: /* 0x23 */
1007/* File: armv5te/OP_NEW_ARRAY.S */
1008    /*
1009     * Allocate an array of objects, specified with the array class
1010     * and a count.
1011     *
1012     * The verifier guarantees that this is an array class, so we don't
1013     * check for it here.
1014     */
1015    /* new-array vA, vB, class@CCCC */
1016    mov     r0, rINST, lsr #12          @ r0<- B
1017    FETCH(r2, 1)                        @ r2<- CCCC
1018    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1019    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1020    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1021    cmp     r1, #0                      @ check length
1022    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1023    bmi     common_errNegativeArraySize @ negative length, bail
1024    cmp     r0, #0                      @ already resolved?
1025    EXPORT_PC()                         @ req'd for resolve, alloc
1026    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1027    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1028
1029/* ------------------------------ */
1030    .balign 64
1031.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1032/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1033    /*
1034     * Create a new array with elements filled from registers.
1035     *
1036     * for: filled-new-array, filled-new-array/range
1037     */
1038    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1039    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1040    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1041    FETCH(r1, 1)                        @ r1<- BBBB
1042    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1043    EXPORT_PC()                         @ need for resolve and alloc
1044    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1045    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1046    cmp     r0, #0                      @ already resolved?
1047    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10488:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1049    mov     r2, #0                      @ r2<- false
1050    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1051    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1052    cmp     r0, #0                      @ got null?
1053    beq     common_exceptionThrown      @ yes, handle exception
1054    b       .LOP_FILLED_NEW_ARRAY_continue
1055
1056/* ------------------------------ */
1057    .balign 64
1058.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1059/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1060/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1061    /*
1062     * Create a new array with elements filled from registers.
1063     *
1064     * for: filled-new-array, filled-new-array/range
1065     */
1066    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1067    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1068    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1069    FETCH(r1, 1)                        @ r1<- BBBB
1070    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1071    EXPORT_PC()                         @ need for resolve and alloc
1072    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1073    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1074    cmp     r0, #0                      @ already resolved?
1075    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10768:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1077    mov     r2, #0                      @ r2<- false
1078    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1079    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1080    cmp     r0, #0                      @ got null?
1081    beq     common_exceptionThrown      @ yes, handle exception
1082    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1083
1084
1085/* ------------------------------ */
1086    .balign 64
1087.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1088/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1089    /* fill-array-data vAA, +BBBBBBBB */
1090    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1091    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1092    mov     r3, rINST, lsr #8           @ r3<- AA
1093    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1094    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1095    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1096    EXPORT_PC();
1097    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1098    cmp     r0, #0                      @ 0 means an exception is thrown
1099    beq     common_exceptionThrown      @ has exception
1100    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1102    GOTO_OPCODE(ip)                     @ jump to next instruction
1103
1104/* ------------------------------ */
1105    .balign 64
1106.L_OP_THROW: /* 0x27 */
1107/* File: armv5te/OP_THROW.S */
1108    /*
1109     * Throw an exception object in the current thread.
1110     */
1111    /* throw vAA */
1112    mov     r2, rINST, lsr #8           @ r2<- AA
1113    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1114    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1115    EXPORT_PC()                         @ exception handler can throw
1116    cmp     r1, #0                      @ null object?
1117    beq     common_errNullObject        @ yes, throw an NPE instead
1118    @ bypass dvmSetException, just store it
1119    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1120    b       common_exceptionThrown
1121
1122/* ------------------------------ */
1123    .balign 64
1124.L_OP_GOTO: /* 0x28 */
1125/* File: armv5te/OP_GOTO.S */
1126    /*
1127     * Unconditional branch, 8-bit offset.
1128     *
1129     * The branch distance is a signed code-unit offset, which we need to
1130     * double to get a byte offset.
1131     */
1132    /* goto +AA */
1133    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1134    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1135    mov     r9, r9, lsl #1              @ r9<- byte offset
1136    bmi     common_backwardBranch       @ backward branch, do periodic checks
1137#if defined(WITH_JIT)
1138    GET_JIT_PROF_TABLE(r0)
1139    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1140    cmp     r0,#0
1141    bne     common_updateProfile
1142    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1143    GOTO_OPCODE(ip)                     @ jump to next instruction
1144#else
1145    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1146    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1147    GOTO_OPCODE(ip)                     @ jump to next instruction
1148#endif
1149
1150/* ------------------------------ */
1151    .balign 64
1152.L_OP_GOTO_16: /* 0x29 */
1153/* File: armv5te/OP_GOTO_16.S */
1154    /*
1155     * Unconditional branch, 16-bit offset.
1156     *
1157     * The branch distance is a signed code-unit offset, which we need to
1158     * double to get a byte offset.
1159     */
1160    /* goto/16 +AAAA */
1161    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1162    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1163    bmi     common_backwardBranch       @ backward branch, do periodic checks
1164#if defined(WITH_JIT)
1165    GET_JIT_PROF_TABLE(r0)
1166    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1167    cmp     r0,#0
1168    bne     common_updateProfile
1169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1170    GOTO_OPCODE(ip)                     @ jump to next instruction
1171#else
1172    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1173    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1174    GOTO_OPCODE(ip)                     @ jump to next instruction
1175#endif
1176
1177/* ------------------------------ */
1178    .balign 64
1179.L_OP_GOTO_32: /* 0x2a */
1180/* File: armv5te/OP_GOTO_32.S */
1181    /*
1182     * Unconditional branch, 32-bit offset.
1183     *
1184     * The branch distance is a signed code-unit offset, which we need to
1185     * double to get a byte offset.
1186     *
1187     * Unlike most opcodes, this one is allowed to branch to itself, so
1188     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1189     * instruction doesn't affect the V flag, so we need to clear it
1190     * explicitly.
1191     */
1192    /* goto/32 +AAAAAAAA */
1193    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1194    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1195    cmp     ip, ip                      @ (clear V flag during stall)
1196    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1197    mov     r9, r0, asl #1              @ r9<- byte offset
1198    ble     common_backwardBranch       @ backward branch, do periodic checks
1199#if defined(WITH_JIT)
1200    GET_JIT_PROF_TABLE(r0)
1201    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1202    cmp     r0,#0
1203    bne     common_updateProfile
1204    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1205    GOTO_OPCODE(ip)                     @ jump to next instruction
1206#else
1207    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1208    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1209    GOTO_OPCODE(ip)                     @ jump to next instruction
1210#endif
1211
1212/* ------------------------------ */
1213    .balign 64
1214.L_OP_PACKED_SWITCH: /* 0x2b */
1215/* File: armv5te/OP_PACKED_SWITCH.S */
1216    /*
1217     * Handle a packed-switch or sparse-switch instruction.  In both cases
1218     * we decode it and hand it off to a helper function.
1219     *
1220     * We don't really expect backward branches in a switch statement, but
1221     * they're perfectly legal, so we check for them here.
1222     *
1223     * for: packed-switch, sparse-switch
1224     */
1225    /* op vAA, +BBBB */
1226    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1227    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1228    mov     r3, rINST, lsr #8           @ r3<- AA
1229    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1230    GET_VREG(r1, r3)                    @ r1<- vAA
1231    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1232    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1233    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1234    bmi     common_backwardBranch       @ backward branch, do periodic checks
1235    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1236#if defined(WITH_JIT)
1237    GET_JIT_PROF_TABLE(r0)
1238    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1239    cmp     r0,#0
1240    bne     common_updateProfile
1241    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1242    GOTO_OPCODE(ip)                     @ jump to next instruction
1243#else
1244    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1245    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1246    GOTO_OPCODE(ip)                     @ jump to next instruction
1247#endif
1248
1249/* ------------------------------ */
1250    .balign 64
1251.L_OP_SPARSE_SWITCH: /* 0x2c */
1252/* File: armv5te/OP_SPARSE_SWITCH.S */
1253/* File: armv5te/OP_PACKED_SWITCH.S */
1254    /*
1255     * Handle a packed-switch or sparse-switch instruction.  In both cases
1256     * we decode it and hand it off to a helper function.
1257     *
1258     * We don't really expect backward branches in a switch statement, but
1259     * they're perfectly legal, so we check for them here.
1260     *
1261     * for: packed-switch, sparse-switch
1262     */
1263    /* op vAA, +BBBB */
1264    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1265    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1266    mov     r3, rINST, lsr #8           @ r3<- AA
1267    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1268    GET_VREG(r1, r3)                    @ r1<- vAA
1269    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1270    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1271    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1272    bmi     common_backwardBranch       @ backward branch, do periodic checks
1273    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1274#if defined(WITH_JIT)
1275    GET_JIT_PROF_TABLE(r0)
1276    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1277    cmp     r0,#0
1278    bne     common_updateProfile
1279    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1280    GOTO_OPCODE(ip)                     @ jump to next instruction
1281#else
1282    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1283    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1284    GOTO_OPCODE(ip)                     @ jump to next instruction
1285#endif
1286
1287
1288/* ------------------------------ */
1289    .balign 64
1290.L_OP_CMPL_FLOAT: /* 0x2d */
1291/* File: arm-vfp/OP_CMPL_FLOAT.S */
1292    /*
1293     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1294     * destination register based on the results of the comparison.
1295     *
1296     * int compare(x, y) {
1297     *     if (x == y) {
1298     *         return 0;
1299     *     } else if (x > y) {
1300     *         return 1;
1301     *     } else if (x < y) {
1302     *         return -1;
1303     *     } else {
1304     *         return -1;
1305     *     }
1306     * }
1307     */
1308    /* op vAA, vBB, vCC */
1309    FETCH(r0, 1)                        @ r0<- CCBB
1310    mov     r9, rINST, lsr #8           @ r9<- AA
1311    and     r2, r0, #255                @ r2<- BB
1312    mov     r3, r0, lsr #8              @ r3<- CC
1313    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1314    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1315    flds    s0, [r2]                    @ s0<- vBB
1316    flds    s1, [r3]                    @ s1<- vCC
1317    fcmpes  s0, s1                      @ compare (vBB, vCC)
1318    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1319    mvn     r0, #0                      @ r0<- -1 (default)
1320    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1321    fmstat                              @ export status flags
1322    movgt   r0, #1                      @ (greater than) r1<- 1
1323    moveq   r0, #0                      @ (equal) r1<- 0
1324    b       .LOP_CMPL_FLOAT_finish          @ argh
1325
1326
1327/* ------------------------------ */
1328    .balign 64
1329.L_OP_CMPG_FLOAT: /* 0x2e */
1330/* File: arm-vfp/OP_CMPG_FLOAT.S */
1331    /*
1332     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1333     * destination register based on the results of the comparison.
1334     *
1335     * int compare(x, y) {
1336     *     if (x == y) {
1337     *         return 0;
1338     *     } else if (x < y) {
1339     *         return -1;
1340     *     } else if (x > y) {
1341     *         return 1;
1342     *     } else {
1343     *         return 1;
1344     *     }
1345     * }
1346     */
1347    /* op vAA, vBB, vCC */
1348    FETCH(r0, 1)                        @ r0<- CCBB
1349    mov     r9, rINST, lsr #8           @ r9<- AA
1350    and     r2, r0, #255                @ r2<- BB
1351    mov     r3, r0, lsr #8              @ r3<- CC
1352    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1353    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1354    flds    s0, [r2]                    @ s0<- vBB
1355    flds    s1, [r3]                    @ s1<- vCC
1356    fcmpes  s0, s1                      @ compare (vBB, vCC)
1357    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1358    mov     r0, #1                      @ r0<- 1 (default)
1359    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1360    fmstat                              @ export status flags
1361    mvnmi   r0, #0                      @ (less than) r1<- -1
1362    moveq   r0, #0                      @ (equal) r1<- 0
1363    b       .LOP_CMPG_FLOAT_finish          @ argh
1364
1365
1366/* ------------------------------ */
1367    .balign 64
1368.L_OP_CMPL_DOUBLE: /* 0x2f */
1369/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1370    /*
1371     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1372     * destination register based on the results of the comparison.
1373     *
1374     * int compare(x, y) {
1375     *     if (x == y) {
1376     *         return 0;
1377     *     } else if (x > y) {
1378     *         return 1;
1379     *     } else if (x < y) {
1380     *         return -1;
1381     *     } else {
1382     *         return -1;
1383     *     }
1384     * }
1385     */
1386    /* op vAA, vBB, vCC */
1387    FETCH(r0, 1)                        @ r0<- CCBB
1388    mov     r9, rINST, lsr #8           @ r9<- AA
1389    and     r2, r0, #255                @ r2<- BB
1390    mov     r3, r0, lsr #8              @ r3<- CC
1391    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1392    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1393    fldd    d0, [r2]                    @ d0<- vBB
1394    fldd    d1, [r3]                    @ d1<- vCC
1395    fcmped  d0, d1                      @ compare (vBB, vCC)
1396    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1397    mvn     r0, #0                      @ r0<- -1 (default)
1398    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1399    fmstat                              @ export status flags
1400    movgt   r0, #1                      @ (greater than) r1<- 1
1401    moveq   r0, #0                      @ (equal) r1<- 0
1402    b       .LOP_CMPL_DOUBLE_finish          @ argh
1403
1404
1405/* ------------------------------ */
1406    .balign 64
1407.L_OP_CMPG_DOUBLE: /* 0x30 */
1408/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1409    /*
1410     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1411     * destination register based on the results of the comparison.
1412     *
1413     * int compare(x, y) {
1414     *     if (x == y) {
1415     *         return 0;
1416     *     } else if (x < y) {
1417     *         return -1;
1418     *     } else if (x > y) {
1419     *         return 1;
1420     *     } else {
1421     *         return 1;
1422     *     }
1423     * }
1424     */
1425    /* op vAA, vBB, vCC */
1426    FETCH(r0, 1)                        @ r0<- CCBB
1427    mov     r9, rINST, lsr #8           @ r9<- AA
1428    and     r2, r0, #255                @ r2<- BB
1429    mov     r3, r0, lsr #8              @ r3<- CC
1430    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1431    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1432    fldd    d0, [r2]                    @ d0<- vBB
1433    fldd    d1, [r3]                    @ d1<- vCC
1434    fcmped  d0, d1                      @ compare (vBB, vCC)
1435    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1436    mov     r0, #1                      @ r0<- 1 (default)
1437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1438    fmstat                              @ export status flags
1439    mvnmi   r0, #0                      @ (less than) r1<- -1
1440    moveq   r0, #0                      @ (equal) r1<- 0
1441    b       .LOP_CMPG_DOUBLE_finish          @ argh
1442
1443
1444/* ------------------------------ */
1445    .balign 64
1446.L_OP_CMP_LONG: /* 0x31 */
1447/* File: armv5te/OP_CMP_LONG.S */
1448    /*
1449     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1450     * register based on the results of the comparison.
1451     *
1452     * We load the full values with LDM, but in practice many values could
1453     * be resolved by only looking at the high word.  This could be made
1454     * faster or slower by splitting the LDM into a pair of LDRs.
1455     *
1456     * If we just wanted to set condition flags, we could do this:
1457     *  subs    ip, r0, r2
1458     *  sbcs    ip, r1, r3
1459     *  subeqs  ip, r0, r2
1460     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1461     * integer value, which we can do with 2 conditional mov/mvn instructions
1462     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1463     * us a constant 5-cycle path plus a branch at the end to the
1464     * instruction epilogue code.  The multi-compare approach below needs
1465     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1466     * in the worst case (the 64-bit values are equal).
1467     */
1468    /* cmp-long vAA, vBB, vCC */
1469    FETCH(r0, 1)                        @ r0<- CCBB
1470    mov     r9, rINST, lsr #8           @ r9<- AA
1471    and     r2, r0, #255                @ r2<- BB
1472    mov     r3, r0, lsr #8              @ r3<- CC
1473    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1474    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1475    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1476    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1477    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1478    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1479    bgt     .LOP_CMP_LONG_greater
1480    subs    r1, r0, r2                  @ r1<- r0 - r2
1481    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1482    bne     .LOP_CMP_LONG_less
1483    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1484
1485/* ------------------------------ */
1486    .balign 64
1487.L_OP_IF_EQ: /* 0x32 */
1488/* File: armv5te/OP_IF_EQ.S */
1489/* File: armv5te/bincmp.S */
1490    /*
1491     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1492     * fragment that specifies the *reverse* comparison to perform, e.g.
1493     * for "if-le" you would use "gt".
1494     *
1495     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1496     */
1497    /* if-cmp vA, vB, +CCCC */
1498    mov     r0, rINST, lsr #8           @ r0<- A+
1499    mov     r1, rINST, lsr #12          @ r1<- B
1500    and     r0, r0, #15
1501    GET_VREG(r3, r1)                    @ r3<- vB
1502    GET_VREG(r2, r0)                    @ r2<- vA
1503    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1504    cmp     r2, r3                      @ compare (vA, vB)
1505    bne  1f                      @ branch to 1 if comparison failed
1506    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1507    movs    r9, r9, asl #1              @ convert to bytes, check sign
1508    bmi     common_backwardBranch       @ yes, do periodic checks
15091:
1510#if defined(WITH_JIT)
1511    GET_JIT_PROF_TABLE(r0)
1512    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1513    b        common_testUpdateProfile
1514#else
1515    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1517    GOTO_OPCODE(ip)                     @ jump to next instruction
1518#endif
1519
1520
1521/* ------------------------------ */
1522    .balign 64
1523.L_OP_IF_NE: /* 0x33 */
1524/* File: armv5te/OP_IF_NE.S */
1525/* File: armv5te/bincmp.S */
1526    /*
1527     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1528     * fragment that specifies the *reverse* comparison to perform, e.g.
1529     * for "if-le" you would use "gt".
1530     *
1531     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1532     */
1533    /* if-cmp vA, vB, +CCCC */
1534    mov     r0, rINST, lsr #8           @ r0<- A+
1535    mov     r1, rINST, lsr #12          @ r1<- B
1536    and     r0, r0, #15
1537    GET_VREG(r3, r1)                    @ r3<- vB
1538    GET_VREG(r2, r0)                    @ r2<- vA
1539    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1540    cmp     r2, r3                      @ compare (vA, vB)
1541    beq  1f                      @ branch to 1 if comparison failed
1542    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1543    movs    r9, r9, asl #1              @ convert to bytes, check sign
1544    bmi     common_backwardBranch       @ yes, do periodic checks
15451:
1546#if defined(WITH_JIT)
1547    GET_JIT_PROF_TABLE(r0)
1548    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1549    b        common_testUpdateProfile
1550#else
1551    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1552    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1553    GOTO_OPCODE(ip)                     @ jump to next instruction
1554#endif
1555
1556
1557/* ------------------------------ */
1558    .balign 64
1559.L_OP_IF_LT: /* 0x34 */
1560/* File: armv5te/OP_IF_LT.S */
1561/* File: armv5te/bincmp.S */
1562    /*
1563     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1564     * fragment that specifies the *reverse* comparison to perform, e.g.
1565     * for "if-le" you would use "gt".
1566     *
1567     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1568     */
1569    /* if-cmp vA, vB, +CCCC */
1570    mov     r0, rINST, lsr #8           @ r0<- A+
1571    mov     r1, rINST, lsr #12          @ r1<- B
1572    and     r0, r0, #15
1573    GET_VREG(r3, r1)                    @ r3<- vB
1574    GET_VREG(r2, r0)                    @ r2<- vA
1575    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1576    cmp     r2, r3                      @ compare (vA, vB)
1577    bge  1f                      @ branch to 1 if comparison failed
1578    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1579    movs    r9, r9, asl #1              @ convert to bytes, check sign
1580    bmi     common_backwardBranch       @ yes, do periodic checks
15811:
1582#if defined(WITH_JIT)
1583    GET_JIT_PROF_TABLE(r0)
1584    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1585    b        common_testUpdateProfile
1586#else
1587    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1588    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1589    GOTO_OPCODE(ip)                     @ jump to next instruction
1590#endif
1591
1592
1593/* ------------------------------ */
1594    .balign 64
1595.L_OP_IF_GE: /* 0x35 */
1596/* File: armv5te/OP_IF_GE.S */
1597/* File: armv5te/bincmp.S */
1598    /*
1599     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1600     * fragment that specifies the *reverse* comparison to perform, e.g.
1601     * for "if-le" you would use "gt".
1602     *
1603     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1604     */
1605    /* if-cmp vA, vB, +CCCC */
1606    mov     r0, rINST, lsr #8           @ r0<- A+
1607    mov     r1, rINST, lsr #12          @ r1<- B
1608    and     r0, r0, #15
1609    GET_VREG(r3, r1)                    @ r3<- vB
1610    GET_VREG(r2, r0)                    @ r2<- vA
1611    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1612    cmp     r2, r3                      @ compare (vA, vB)
1613    blt  1f                      @ branch to 1 if comparison failed
1614    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1615    movs    r9, r9, asl #1              @ convert to bytes, check sign
1616    bmi     common_backwardBranch       @ yes, do periodic checks
16171:
1618#if defined(WITH_JIT)
1619    GET_JIT_PROF_TABLE(r0)
1620    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1621    b        common_testUpdateProfile
1622#else
1623    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1624    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1625    GOTO_OPCODE(ip)                     @ jump to next instruction
1626#endif
1627
1628
1629/* ------------------------------ */
1630    .balign 64
1631.L_OP_IF_GT: /* 0x36 */
1632/* File: armv5te/OP_IF_GT.S */
1633/* File: armv5te/bincmp.S */
1634    /*
1635     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1636     * fragment that specifies the *reverse* comparison to perform, e.g.
1637     * for "if-le" you would use "gt".
1638     *
1639     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1640     */
1641    /* if-cmp vA, vB, +CCCC */
1642    mov     r0, rINST, lsr #8           @ r0<- A+
1643    mov     r1, rINST, lsr #12          @ r1<- B
1644    and     r0, r0, #15
1645    GET_VREG(r3, r1)                    @ r3<- vB
1646    GET_VREG(r2, r0)                    @ r2<- vA
1647    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1648    cmp     r2, r3                      @ compare (vA, vB)
1649    ble  1f                      @ branch to 1 if comparison failed
1650    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1651    movs    r9, r9, asl #1              @ convert to bytes, check sign
1652    bmi     common_backwardBranch       @ yes, do periodic checks
16531:
1654#if defined(WITH_JIT)
1655    GET_JIT_PROF_TABLE(r0)
1656    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1657    b        common_testUpdateProfile
1658#else
1659    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1660    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1661    GOTO_OPCODE(ip)                     @ jump to next instruction
1662#endif
1663
1664
1665/* ------------------------------ */
1666    .balign 64
1667.L_OP_IF_LE: /* 0x37 */
1668/* File: armv5te/OP_IF_LE.S */
1669/* File: armv5te/bincmp.S */
1670    /*
1671     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1672     * fragment that specifies the *reverse* comparison to perform, e.g.
1673     * for "if-le" you would use "gt".
1674     *
1675     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1676     */
1677    /* if-cmp vA, vB, +CCCC */
1678    mov     r0, rINST, lsr #8           @ r0<- A+
1679    mov     r1, rINST, lsr #12          @ r1<- B
1680    and     r0, r0, #15
1681    GET_VREG(r3, r1)                    @ r3<- vB
1682    GET_VREG(r2, r0)                    @ r2<- vA
1683    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1684    cmp     r2, r3                      @ compare (vA, vB)
1685    bgt  1f                      @ branch to 1 if comparison failed
1686    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1687    movs    r9, r9, asl #1              @ convert to bytes, check sign
1688    bmi     common_backwardBranch       @ yes, do periodic checks
16891:
1690#if defined(WITH_JIT)
1691    GET_JIT_PROF_TABLE(r0)
1692    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1693    b        common_testUpdateProfile
1694#else
1695    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1697    GOTO_OPCODE(ip)                     @ jump to next instruction
1698#endif
1699
1700
1701/* ------------------------------ */
1702    .balign 64
1703.L_OP_IF_EQZ: /* 0x38 */
1704/* File: armv5te/OP_IF_EQZ.S */
1705/* File: armv5te/zcmp.S */
1706    /*
1707     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1708     * fragment that specifies the *reverse* comparison to perform, e.g.
1709     * for "if-le" you would use "gt".
1710     *
1711     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1712     */
1713    /* if-cmp vAA, +BBBB */
1714    mov     r0, rINST, lsr #8           @ r0<- AA
1715    GET_VREG(r2, r0)                    @ r2<- vAA
1716    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1717    cmp     r2, #0                      @ compare (vA, 0)
1718    bne  1f                      @ branch to 1 if comparison failed
1719    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1720    movs    r9, r9, asl #1              @ convert to bytes, check sign
1721    bmi     common_backwardBranch       @ backward branch, do periodic checks
17221:
1723#if defined(WITH_JIT)
1724    GET_JIT_PROF_TABLE(r0)
1725    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1726    cmp     r0,#0
1727    bne     common_updateProfile
1728    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1729    GOTO_OPCODE(ip)                     @ jump to next instruction
1730#else
1731    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1732    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1733    GOTO_OPCODE(ip)                     @ jump to next instruction
1734#endif
1735
1736
1737/* ------------------------------ */
1738    .balign 64
1739.L_OP_IF_NEZ: /* 0x39 */
1740/* File: armv5te/OP_IF_NEZ.S */
1741/* File: armv5te/zcmp.S */
1742    /*
1743     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1744     * fragment that specifies the *reverse* comparison to perform, e.g.
1745     * for "if-le" you would use "gt".
1746     *
1747     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1748     */
1749    /* if-cmp vAA, +BBBB */
1750    mov     r0, rINST, lsr #8           @ r0<- AA
1751    GET_VREG(r2, r0)                    @ r2<- vAA
1752    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1753    cmp     r2, #0                      @ compare (vA, 0)
1754    beq  1f                      @ branch to 1 if comparison failed
1755    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1756    movs    r9, r9, asl #1              @ convert to bytes, check sign
1757    bmi     common_backwardBranch       @ backward branch, do periodic checks
17581:
1759#if defined(WITH_JIT)
1760    GET_JIT_PROF_TABLE(r0)
1761    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1762    cmp     r0,#0
1763    bne     common_updateProfile
1764    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1765    GOTO_OPCODE(ip)                     @ jump to next instruction
1766#else
1767    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1768    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1769    GOTO_OPCODE(ip)                     @ jump to next instruction
1770#endif
1771
1772
1773/* ------------------------------ */
1774    .balign 64
1775.L_OP_IF_LTZ: /* 0x3a */
1776/* File: armv5te/OP_IF_LTZ.S */
1777/* File: armv5te/zcmp.S */
1778    /*
1779     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1780     * fragment that specifies the *reverse* comparison to perform, e.g.
1781     * for "if-le" you would use "gt".
1782     *
1783     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1784     */
1785    /* if-cmp vAA, +BBBB */
1786    mov     r0, rINST, lsr #8           @ r0<- AA
1787    GET_VREG(r2, r0)                    @ r2<- vAA
1788    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1789    cmp     r2, #0                      @ compare (vA, 0)
1790    bge  1f                      @ branch to 1 if comparison failed
1791    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1792    movs    r9, r9, asl #1              @ convert to bytes, check sign
1793    bmi     common_backwardBranch       @ backward branch, do periodic checks
17941:
1795#if defined(WITH_JIT)
1796    GET_JIT_PROF_TABLE(r0)
1797    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1798    cmp     r0,#0
1799    bne     common_updateProfile
1800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1801    GOTO_OPCODE(ip)                     @ jump to next instruction
1802#else
1803    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1804    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1805    GOTO_OPCODE(ip)                     @ jump to next instruction
1806#endif
1807
1808
1809/* ------------------------------ */
1810    .balign 64
1811.L_OP_IF_GEZ: /* 0x3b */
1812/* File: armv5te/OP_IF_GEZ.S */
1813/* File: armv5te/zcmp.S */
1814    /*
1815     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1816     * fragment that specifies the *reverse* comparison to perform, e.g.
1817     * for "if-le" you would use "gt".
1818     *
1819     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1820     */
1821    /* if-cmp vAA, +BBBB */
1822    mov     r0, rINST, lsr #8           @ r0<- AA
1823    GET_VREG(r2, r0)                    @ r2<- vAA
1824    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1825    cmp     r2, #0                      @ compare (vA, 0)
1826    blt  1f                      @ branch to 1 if comparison failed
1827    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1828    movs    r9, r9, asl #1              @ convert to bytes, check sign
1829    bmi     common_backwardBranch       @ backward branch, do periodic checks
18301:
1831#if defined(WITH_JIT)
1832    GET_JIT_PROF_TABLE(r0)
1833    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1834    cmp     r0,#0
1835    bne     common_updateProfile
1836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1837    GOTO_OPCODE(ip)                     @ jump to next instruction
1838#else
1839    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1841    GOTO_OPCODE(ip)                     @ jump to next instruction
1842#endif
1843
1844
1845/* ------------------------------ */
1846    .balign 64
1847.L_OP_IF_GTZ: /* 0x3c */
1848/* File: armv5te/OP_IF_GTZ.S */
1849/* File: armv5te/zcmp.S */
1850    /*
1851     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1852     * fragment that specifies the *reverse* comparison to perform, e.g.
1853     * for "if-le" you would use "gt".
1854     *
1855     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1856     */
1857    /* if-cmp vAA, +BBBB */
1858    mov     r0, rINST, lsr #8           @ r0<- AA
1859    GET_VREG(r2, r0)                    @ r2<- vAA
1860    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1861    cmp     r2, #0                      @ compare (vA, 0)
1862    ble  1f                      @ branch to 1 if comparison failed
1863    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1864    movs    r9, r9, asl #1              @ convert to bytes, check sign
1865    bmi     common_backwardBranch       @ backward branch, do periodic checks
18661:
1867#if defined(WITH_JIT)
1868    GET_JIT_PROF_TABLE(r0)
1869    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1870    cmp     r0,#0
1871    bne     common_updateProfile
1872    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1873    GOTO_OPCODE(ip)                     @ jump to next instruction
1874#else
1875    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1876    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1877    GOTO_OPCODE(ip)                     @ jump to next instruction
1878#endif
1879
1880
1881/* ------------------------------ */
1882    .balign 64
1883.L_OP_IF_LEZ: /* 0x3d */
1884/* File: armv5te/OP_IF_LEZ.S */
1885/* File: armv5te/zcmp.S */
1886    /*
1887     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1888     * fragment that specifies the *reverse* comparison to perform, e.g.
1889     * for "if-le" you would use "gt".
1890     *
1891     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1892     */
1893    /* if-cmp vAA, +BBBB */
1894    mov     r0, rINST, lsr #8           @ r0<- AA
1895    GET_VREG(r2, r0)                    @ r2<- vAA
1896    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1897    cmp     r2, #0                      @ compare (vA, 0)
1898    bgt  1f                      @ branch to 1 if comparison failed
1899    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1900    movs    r9, r9, asl #1              @ convert to bytes, check sign
1901    bmi     common_backwardBranch       @ backward branch, do periodic checks
19021:
1903#if defined(WITH_JIT)
1904    GET_JIT_PROF_TABLE(r0)
1905    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1906    cmp     r0,#0
1907    bne     common_updateProfile
1908    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1909    GOTO_OPCODE(ip)                     @ jump to next instruction
1910#else
1911    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1912    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1913    GOTO_OPCODE(ip)                     @ jump to next instruction
1914#endif
1915
1916
1917/* ------------------------------ */
1918    .balign 64
1919.L_OP_UNUSED_3E: /* 0x3e */
1920/* File: armv5te/OP_UNUSED_3E.S */
1921/* File: armv5te/unused.S */
1922    bl      common_abort
1923
1924
1925/* ------------------------------ */
1926    .balign 64
1927.L_OP_UNUSED_3F: /* 0x3f */
1928/* File: armv5te/OP_UNUSED_3F.S */
1929/* File: armv5te/unused.S */
1930    bl      common_abort
1931
1932
1933/* ------------------------------ */
1934    .balign 64
1935.L_OP_UNUSED_40: /* 0x40 */
1936/* File: armv5te/OP_UNUSED_40.S */
1937/* File: armv5te/unused.S */
1938    bl      common_abort
1939
1940
1941/* ------------------------------ */
1942    .balign 64
1943.L_OP_UNUSED_41: /* 0x41 */
1944/* File: armv5te/OP_UNUSED_41.S */
1945/* File: armv5te/unused.S */
1946    bl      common_abort
1947
1948
1949/* ------------------------------ */
1950    .balign 64
1951.L_OP_UNUSED_42: /* 0x42 */
1952/* File: armv5te/OP_UNUSED_42.S */
1953/* File: armv5te/unused.S */
1954    bl      common_abort
1955
1956
1957/* ------------------------------ */
1958    .balign 64
1959.L_OP_UNUSED_43: /* 0x43 */
1960/* File: armv5te/OP_UNUSED_43.S */
1961/* File: armv5te/unused.S */
1962    bl      common_abort
1963
1964
1965/* ------------------------------ */
1966    .balign 64
1967.L_OP_AGET: /* 0x44 */
1968/* File: armv5te/OP_AGET.S */
1969    /*
1970     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1971     *
1972     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1973     * instructions.  We use a pair of FETCH_Bs instead.
1974     *
1975     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1976     */
1977    /* op vAA, vBB, vCC */
1978    FETCH_B(r2, 1, 0)                   @ r2<- BB
1979    mov     r9, rINST, lsr #8           @ r9<- AA
1980    FETCH_B(r3, 1, 1)                   @ r3<- CC
1981    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1982    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1983    cmp     r0, #0                      @ null array object?
1984    beq     common_errNullObject        @ yes, bail
1985    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1986    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1987    cmp     r1, r3                      @ compare unsigned index, length
1988    bcs     common_errArrayIndex        @ index >= length, bail
1989    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1990    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
1991    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1992    SET_VREG(r2, r9)                    @ vAA<- r2
1993    GOTO_OPCODE(ip)                     @ jump to next instruction
1994
1995/* ------------------------------ */
1996    .balign 64
1997.L_OP_AGET_WIDE: /* 0x45 */
1998/* File: armv5te/OP_AGET_WIDE.S */
1999    /*
2000     * Array get, 64 bits.  vAA <- vBB[vCC].
2001     *
2002     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2003     */
2004    /* aget-wide vAA, vBB, vCC */
2005    FETCH(r0, 1)                        @ r0<- CCBB
2006    mov     r9, rINST, lsr #8           @ r9<- AA
2007    and     r2, r0, #255                @ r2<- BB
2008    mov     r3, r0, lsr #8              @ r3<- CC
2009    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2010    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2011    cmp     r0, #0                      @ null array object?
2012    beq     common_errNullObject        @ yes, bail
2013    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2014    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2015    cmp     r1, r3                      @ compare unsigned index, length
2016    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2017    b       common_errArrayIndex        @ index >= length, bail
2018    @ May want to swap the order of these two branches depending on how the
2019    @ branch prediction (if any) handles conditional forward branches vs.
2020    @ unconditional forward branches.
2021
2022/* ------------------------------ */
2023    .balign 64
2024.L_OP_AGET_OBJECT: /* 0x46 */
2025/* File: armv5te/OP_AGET_OBJECT.S */
2026/* File: armv5te/OP_AGET.S */
2027    /*
2028     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2029     *
2030     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2031     * instructions.  We use a pair of FETCH_Bs instead.
2032     *
2033     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2034     */
2035    /* op vAA, vBB, vCC */
2036    FETCH_B(r2, 1, 0)                   @ r2<- BB
2037    mov     r9, rINST, lsr #8           @ r9<- AA
2038    FETCH_B(r3, 1, 1)                   @ r3<- CC
2039    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2040    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2041    cmp     r0, #0                      @ null array object?
2042    beq     common_errNullObject        @ yes, bail
2043    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2044    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2045    cmp     r1, r3                      @ compare unsigned index, length
2046    bcs     common_errArrayIndex        @ index >= length, bail
2047    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2048    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2049    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2050    SET_VREG(r2, r9)                    @ vAA<- r2
2051    GOTO_OPCODE(ip)                     @ jump to next instruction
2052
2053
2054/* ------------------------------ */
2055    .balign 64
2056.L_OP_AGET_BOOLEAN: /* 0x47 */
2057/* File: armv5te/OP_AGET_BOOLEAN.S */
2058/* File: armv5te/OP_AGET.S */
2059    /*
2060     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2061     *
2062     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2063     * instructions.  We use a pair of FETCH_Bs instead.
2064     *
2065     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2066     */
2067    /* op vAA, vBB, vCC */
2068    FETCH_B(r2, 1, 0)                   @ r2<- BB
2069    mov     r9, rINST, lsr #8           @ r9<- AA
2070    FETCH_B(r3, 1, 1)                   @ r3<- CC
2071    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2072    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2073    cmp     r0, #0                      @ null array object?
2074    beq     common_errNullObject        @ yes, bail
2075    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2076    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2077    cmp     r1, r3                      @ compare unsigned index, length
2078    bcs     common_errArrayIndex        @ index >= length, bail
2079    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2080    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2082    SET_VREG(r2, r9)                    @ vAA<- r2
2083    GOTO_OPCODE(ip)                     @ jump to next instruction
2084
2085
2086/* ------------------------------ */
2087    .balign 64
2088.L_OP_AGET_BYTE: /* 0x48 */
2089/* File: armv5te/OP_AGET_BYTE.S */
2090/* File: armv5te/OP_AGET.S */
2091    /*
2092     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2093     *
2094     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2095     * instructions.  We use a pair of FETCH_Bs instead.
2096     *
2097     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2098     */
2099    /* op vAA, vBB, vCC */
2100    FETCH_B(r2, 1, 0)                   @ r2<- BB
2101    mov     r9, rINST, lsr #8           @ r9<- AA
2102    FETCH_B(r3, 1, 1)                   @ r3<- CC
2103    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2104    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2105    cmp     r0, #0                      @ null array object?
2106    beq     common_errNullObject        @ yes, bail
2107    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2108    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2109    cmp     r1, r3                      @ compare unsigned index, length
2110    bcs     common_errArrayIndex        @ index >= length, bail
2111    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2112    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2113    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2114    SET_VREG(r2, r9)                    @ vAA<- r2
2115    GOTO_OPCODE(ip)                     @ jump to next instruction
2116
2117
2118/* ------------------------------ */
2119    .balign 64
2120.L_OP_AGET_CHAR: /* 0x49 */
2121/* File: armv5te/OP_AGET_CHAR.S */
2122/* File: armv5te/OP_AGET.S */
2123    /*
2124     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2125     *
2126     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2127     * instructions.  We use a pair of FETCH_Bs instead.
2128     *
2129     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2130     */
2131    /* op vAA, vBB, vCC */
2132    FETCH_B(r2, 1, 0)                   @ r2<- BB
2133    mov     r9, rINST, lsr #8           @ r9<- AA
2134    FETCH_B(r3, 1, 1)                   @ r3<- CC
2135    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2136    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2137    cmp     r0, #0                      @ null array object?
2138    beq     common_errNullObject        @ yes, bail
2139    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2140    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2141    cmp     r1, r3                      @ compare unsigned index, length
2142    bcs     common_errArrayIndex        @ index >= length, bail
2143    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2144    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2146    SET_VREG(r2, r9)                    @ vAA<- r2
2147    GOTO_OPCODE(ip)                     @ jump to next instruction
2148
2149
2150/* ------------------------------ */
2151    .balign 64
2152.L_OP_AGET_SHORT: /* 0x4a */
2153/* File: armv5te/OP_AGET_SHORT.S */
2154/* File: armv5te/OP_AGET.S */
2155    /*
2156     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2157     *
2158     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2159     * instructions.  We use a pair of FETCH_Bs instead.
2160     *
2161     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2162     */
2163    /* op vAA, vBB, vCC */
2164    FETCH_B(r2, 1, 0)                   @ r2<- BB
2165    mov     r9, rINST, lsr #8           @ r9<- AA
2166    FETCH_B(r3, 1, 1)                   @ r3<- CC
2167    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2168    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2169    cmp     r0, #0                      @ null array object?
2170    beq     common_errNullObject        @ yes, bail
2171    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2172    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2173    cmp     r1, r3                      @ compare unsigned index, length
2174    bcs     common_errArrayIndex        @ index >= length, bail
2175    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2176    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2177    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2178    SET_VREG(r2, r9)                    @ vAA<- r2
2179    GOTO_OPCODE(ip)                     @ jump to next instruction
2180
2181
2182/* ------------------------------ */
2183    .balign 64
2184.L_OP_APUT: /* 0x4b */
2185/* File: armv5te/OP_APUT.S */
2186    /*
2187     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2188     *
2189     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2190     * instructions.  We use a pair of FETCH_Bs instead.
2191     *
2192     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2193     */
2194    /* op vAA, vBB, vCC */
2195    FETCH_B(r2, 1, 0)                   @ r2<- BB
2196    mov     r9, rINST, lsr #8           @ r9<- AA
2197    FETCH_B(r3, 1, 1)                   @ r3<- CC
2198    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2199    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2200    cmp     r0, #0                      @ null array object?
2201    beq     common_errNullObject        @ yes, bail
2202    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2203    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2204    cmp     r1, r3                      @ compare unsigned index, length
2205    bcs     common_errArrayIndex        @ index >= length, bail
2206    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2207    GET_VREG(r2, r9)                    @ r2<- vAA
2208    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2209    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2210    GOTO_OPCODE(ip)                     @ jump to next instruction
2211
2212/* ------------------------------ */
2213    .balign 64
2214.L_OP_APUT_WIDE: /* 0x4c */
2215/* File: armv5te/OP_APUT_WIDE.S */
2216    /*
2217     * Array put, 64 bits.  vBB[vCC] <- vAA.
2218     *
2219     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2220     */
2221    /* aput-wide vAA, vBB, vCC */
2222    FETCH(r0, 1)                        @ r0<- CCBB
2223    mov     r9, rINST, lsr #8           @ r9<- AA
2224    and     r2, r0, #255                @ r2<- BB
2225    mov     r3, r0, lsr #8              @ r3<- CC
2226    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2227    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2228    cmp     r0, #0                      @ null array object?
2229    beq     common_errNullObject        @ yes, bail
2230    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2231    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2232    cmp     r1, r3                      @ compare unsigned index, length
2233    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2234    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2235    b       common_errArrayIndex        @ index >= length, bail
2236    @ May want to swap the order of these two branches depending on how the
2237    @ branch prediction (if any) handles conditional forward branches vs.
2238    @ unconditional forward branches.
2239
2240/* ------------------------------ */
2241    .balign 64
2242.L_OP_APUT_OBJECT: /* 0x4d */
2243/* File: armv5te/OP_APUT_OBJECT.S */
2244    /*
2245     * Store an object into an array.  vBB[vCC] <- vAA.
2246     *
2247     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2248     * instructions.  We use a pair of FETCH_Bs instead.
2249     */
2250    /* op vAA, vBB, vCC */
2251    FETCH(r0, 1)                        @ r0<- CCBB
2252    mov     r9, rINST, lsr #8           @ r9<- AA
2253    and     r2, r0, #255                @ r2<- BB
2254    mov     r3, r0, lsr #8              @ r3<- CC
2255    GET_VREG(r1, r2)                    @ r1<- vBB (array object)
2256    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2257    cmp     r1, #0                      @ null array object?
2258    GET_VREG(r9, r9)                    @ r9<- vAA
2259    beq     common_errNullObject        @ yes, bail
2260    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2261    add     r10, r1, r0, lsl #2         @ r10<- arrayObj + index*width
2262    cmp     r0, r3                      @ compare unsigned index, length
2263    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2264    b       common_errArrayIndex        @ index >= length, bail
2265
2266
2267/* ------------------------------ */
2268    .balign 64
2269.L_OP_APUT_BOOLEAN: /* 0x4e */
2270/* File: armv5te/OP_APUT_BOOLEAN.S */
2271/* File: armv5te/OP_APUT.S */
2272    /*
2273     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2274     *
2275     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2276     * instructions.  We use a pair of FETCH_Bs instead.
2277     *
2278     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2279     */
2280    /* op vAA, vBB, vCC */
2281    FETCH_B(r2, 1, 0)                   @ r2<- BB
2282    mov     r9, rINST, lsr #8           @ r9<- AA
2283    FETCH_B(r3, 1, 1)                   @ r3<- CC
2284    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2285    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2286    cmp     r0, #0                      @ null array object?
2287    beq     common_errNullObject        @ yes, bail
2288    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2289    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2290    cmp     r1, r3                      @ compare unsigned index, length
2291    bcs     common_errArrayIndex        @ index >= length, bail
2292    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2293    GET_VREG(r2, r9)                    @ r2<- vAA
2294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2295    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2296    GOTO_OPCODE(ip)                     @ jump to next instruction
2297
2298
2299/* ------------------------------ */
2300    .balign 64
2301.L_OP_APUT_BYTE: /* 0x4f */
2302/* File: armv5te/OP_APUT_BYTE.S */
2303/* File: armv5te/OP_APUT.S */
2304    /*
2305     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2306     *
2307     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2308     * instructions.  We use a pair of FETCH_Bs instead.
2309     *
2310     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2311     */
2312    /* op vAA, vBB, vCC */
2313    FETCH_B(r2, 1, 0)                   @ r2<- BB
2314    mov     r9, rINST, lsr #8           @ r9<- AA
2315    FETCH_B(r3, 1, 1)                   @ r3<- CC
2316    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2317    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2318    cmp     r0, #0                      @ null array object?
2319    beq     common_errNullObject        @ yes, bail
2320    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2321    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2322    cmp     r1, r3                      @ compare unsigned index, length
2323    bcs     common_errArrayIndex        @ index >= length, bail
2324    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2325    GET_VREG(r2, r9)                    @ r2<- vAA
2326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2327    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2328    GOTO_OPCODE(ip)                     @ jump to next instruction
2329
2330
2331/* ------------------------------ */
2332    .balign 64
2333.L_OP_APUT_CHAR: /* 0x50 */
2334/* File: armv5te/OP_APUT_CHAR.S */
2335/* File: armv5te/OP_APUT.S */
2336    /*
2337     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2338     *
2339     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2340     * instructions.  We use a pair of FETCH_Bs instead.
2341     *
2342     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2343     */
2344    /* op vAA, vBB, vCC */
2345    FETCH_B(r2, 1, 0)                   @ r2<- BB
2346    mov     r9, rINST, lsr #8           @ r9<- AA
2347    FETCH_B(r3, 1, 1)                   @ r3<- CC
2348    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2349    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2350    cmp     r0, #0                      @ null array object?
2351    beq     common_errNullObject        @ yes, bail
2352    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2353    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2354    cmp     r1, r3                      @ compare unsigned index, length
2355    bcs     common_errArrayIndex        @ index >= length, bail
2356    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2357    GET_VREG(r2, r9)                    @ r2<- vAA
2358    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2359    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2360    GOTO_OPCODE(ip)                     @ jump to next instruction
2361
2362
2363/* ------------------------------ */
2364    .balign 64
2365.L_OP_APUT_SHORT: /* 0x51 */
2366/* File: armv5te/OP_APUT_SHORT.S */
2367/* File: armv5te/OP_APUT.S */
2368    /*
2369     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2370     *
2371     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2372     * instructions.  We use a pair of FETCH_Bs instead.
2373     *
2374     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2375     */
2376    /* op vAA, vBB, vCC */
2377    FETCH_B(r2, 1, 0)                   @ r2<- BB
2378    mov     r9, rINST, lsr #8           @ r9<- AA
2379    FETCH_B(r3, 1, 1)                   @ r3<- CC
2380    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2381    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2382    cmp     r0, #0                      @ null array object?
2383    beq     common_errNullObject        @ yes, bail
2384    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2385    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2386    cmp     r1, r3                      @ compare unsigned index, length
2387    bcs     common_errArrayIndex        @ index >= length, bail
2388    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2389    GET_VREG(r2, r9)                    @ r2<- vAA
2390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2391    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2392    GOTO_OPCODE(ip)                     @ jump to next instruction
2393
2394
2395/* ------------------------------ */
2396    .balign 64
2397.L_OP_IGET: /* 0x52 */
2398/* File: armv5te/OP_IGET.S */
2399    /*
2400     * General 32-bit instance field get.
2401     *
2402     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2403     */
2404    /* op vA, vB, field@CCCC */
2405    mov     r0, rINST, lsr #12          @ r0<- B
2406    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2407    FETCH(r1, 1)                        @ r1<- field ref CCCC
2408    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2409    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2410    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2411    cmp     r0, #0                      @ is resolved entry null?
2412    bne     .LOP_IGET_finish          @ no, already resolved
24138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2414    EXPORT_PC()                         @ resolve() could throw
2415    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2416    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2417    cmp     r0, #0
2418    bne     .LOP_IGET_finish
2419    b       common_exceptionThrown
2420
2421/* ------------------------------ */
2422    .balign 64
2423.L_OP_IGET_WIDE: /* 0x53 */
2424/* File: armv5te/OP_IGET_WIDE.S */
2425    /*
2426     * Wide 32-bit instance field get.
2427     */
2428    /* iget-wide vA, vB, field@CCCC */
2429    mov     r0, rINST, lsr #12          @ r0<- B
2430    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2431    FETCH(r1, 1)                        @ r1<- field ref CCCC
2432    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2433    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2434    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2435    cmp     r0, #0                      @ is resolved entry null?
2436    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24378:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2438    EXPORT_PC()                         @ resolve() could throw
2439    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2440    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2441    cmp     r0, #0
2442    bne     .LOP_IGET_WIDE_finish
2443    b       common_exceptionThrown
2444
2445/* ------------------------------ */
2446    .balign 64
2447.L_OP_IGET_OBJECT: /* 0x54 */
2448/* File: armv5te/OP_IGET_OBJECT.S */
2449/* File: armv5te/OP_IGET.S */
2450    /*
2451     * General 32-bit instance field get.
2452     *
2453     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2454     */
2455    /* op vA, vB, field@CCCC */
2456    mov     r0, rINST, lsr #12          @ r0<- B
2457    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2458    FETCH(r1, 1)                        @ r1<- field ref CCCC
2459    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2460    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2461    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2462    cmp     r0, #0                      @ is resolved entry null?
2463    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24648:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2465    EXPORT_PC()                         @ resolve() could throw
2466    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2467    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2468    cmp     r0, #0
2469    bne     .LOP_IGET_OBJECT_finish
2470    b       common_exceptionThrown
2471
2472
2473/* ------------------------------ */
2474    .balign 64
2475.L_OP_IGET_BOOLEAN: /* 0x55 */
2476/* File: armv5te/OP_IGET_BOOLEAN.S */
2477@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2478/* File: armv5te/OP_IGET.S */
2479    /*
2480     * General 32-bit instance field get.
2481     *
2482     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2483     */
2484    /* op vA, vB, field@CCCC */
2485    mov     r0, rINST, lsr #12          @ r0<- B
2486    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2487    FETCH(r1, 1)                        @ r1<- field ref CCCC
2488    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2489    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2490    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2491    cmp     r0, #0                      @ is resolved entry null?
2492    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
24938:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2494    EXPORT_PC()                         @ resolve() could throw
2495    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2496    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2497    cmp     r0, #0
2498    bne     .LOP_IGET_BOOLEAN_finish
2499    b       common_exceptionThrown
2500
2501
2502/* ------------------------------ */
2503    .balign 64
2504.L_OP_IGET_BYTE: /* 0x56 */
2505/* File: armv5te/OP_IGET_BYTE.S */
2506@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2507/* File: armv5te/OP_IGET.S */
2508    /*
2509     * General 32-bit instance field get.
2510     *
2511     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2512     */
2513    /* op vA, vB, field@CCCC */
2514    mov     r0, rINST, lsr #12          @ r0<- B
2515    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2516    FETCH(r1, 1)                        @ r1<- field ref CCCC
2517    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2518    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2519    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2520    cmp     r0, #0                      @ is resolved entry null?
2521    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25228:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2523    EXPORT_PC()                         @ resolve() could throw
2524    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2525    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2526    cmp     r0, #0
2527    bne     .LOP_IGET_BYTE_finish
2528    b       common_exceptionThrown
2529
2530
2531/* ------------------------------ */
2532    .balign 64
2533.L_OP_IGET_CHAR: /* 0x57 */
2534/* File: armv5te/OP_IGET_CHAR.S */
2535@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2536/* File: armv5te/OP_IGET.S */
2537    /*
2538     * General 32-bit instance field get.
2539     *
2540     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2541     */
2542    /* op vA, vB, field@CCCC */
2543    mov     r0, rINST, lsr #12          @ r0<- B
2544    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2545    FETCH(r1, 1)                        @ r1<- field ref CCCC
2546    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2547    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2548    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2549    cmp     r0, #0                      @ is resolved entry null?
2550    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25518:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2552    EXPORT_PC()                         @ resolve() could throw
2553    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2554    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2555    cmp     r0, #0
2556    bne     .LOP_IGET_CHAR_finish
2557    b       common_exceptionThrown
2558
2559
2560/* ------------------------------ */
2561    .balign 64
2562.L_OP_IGET_SHORT: /* 0x58 */
2563/* File: armv5te/OP_IGET_SHORT.S */
2564@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2565/* File: armv5te/OP_IGET.S */
2566    /*
2567     * General 32-bit instance field get.
2568     *
2569     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2570     */
2571    /* op vA, vB, field@CCCC */
2572    mov     r0, rINST, lsr #12          @ r0<- B
2573    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2574    FETCH(r1, 1)                        @ r1<- field ref CCCC
2575    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2576    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2577    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2578    cmp     r0, #0                      @ is resolved entry null?
2579    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25808:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2581    EXPORT_PC()                         @ resolve() could throw
2582    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2583    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2584    cmp     r0, #0
2585    bne     .LOP_IGET_SHORT_finish
2586    b       common_exceptionThrown
2587
2588
2589/* ------------------------------ */
2590    .balign 64
2591.L_OP_IPUT: /* 0x59 */
2592/* File: armv5te/OP_IPUT.S */
2593    /*
2594     * General 32-bit instance field put.
2595     *
2596     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2597     */
2598    /* op vA, vB, field@CCCC */
2599    mov     r0, rINST, lsr #12          @ r0<- B
2600    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2601    FETCH(r1, 1)                        @ r1<- field ref CCCC
2602    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2603    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2604    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2605    cmp     r0, #0                      @ is resolved entry null?
2606    bne     .LOP_IPUT_finish          @ no, already resolved
26078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2608    EXPORT_PC()                         @ resolve() could throw
2609    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2610    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2611    cmp     r0, #0                      @ success?
2612    bne     .LOP_IPUT_finish          @ yes, finish up
2613    b       common_exceptionThrown
2614
2615/* ------------------------------ */
2616    .balign 64
2617.L_OP_IPUT_WIDE: /* 0x5a */
2618/* File: armv5te/OP_IPUT_WIDE.S */
2619    /* iput-wide vA, vB, field@CCCC */
2620    mov     r0, rINST, lsr #12          @ r0<- B
2621    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2622    FETCH(r1, 1)                        @ r1<- field ref CCCC
2623    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2624    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2625    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2626    cmp     r0, #0                      @ is resolved entry null?
2627    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26288:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2629    EXPORT_PC()                         @ resolve() could throw
2630    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2631    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2632    cmp     r0, #0                      @ success?
2633    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2634    b       common_exceptionThrown
2635
2636/* ------------------------------ */
2637    .balign 64
2638.L_OP_IPUT_OBJECT: /* 0x5b */
2639/* File: armv5te/OP_IPUT_OBJECT.S */
2640/* File: armv5te/OP_IPUT.S */
2641    /*
2642     * General 32-bit instance field put.
2643     *
2644     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2645     */
2646    /* op vA, vB, field@CCCC */
2647    mov     r0, rINST, lsr #12          @ r0<- B
2648    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2649    FETCH(r1, 1)                        @ r1<- field ref CCCC
2650    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2651    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2652    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2653    cmp     r0, #0                      @ is resolved entry null?
2654    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26558:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2656    EXPORT_PC()                         @ resolve() could throw
2657    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2658    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2659    cmp     r0, #0                      @ success?
2660    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2661    b       common_exceptionThrown
2662
2663
2664/* ------------------------------ */
2665    .balign 64
2666.L_OP_IPUT_BOOLEAN: /* 0x5c */
2667/* File: armv5te/OP_IPUT_BOOLEAN.S */
2668@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2669/* File: armv5te/OP_IPUT.S */
2670    /*
2671     * General 32-bit instance field put.
2672     *
2673     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2674     */
2675    /* op vA, vB, field@CCCC */
2676    mov     r0, rINST, lsr #12          @ r0<- B
2677    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2678    FETCH(r1, 1)                        @ r1<- field ref CCCC
2679    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2680    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2681    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2682    cmp     r0, #0                      @ is resolved entry null?
2683    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26848:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2685    EXPORT_PC()                         @ resolve() could throw
2686    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2687    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2688    cmp     r0, #0                      @ success?
2689    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2690    b       common_exceptionThrown
2691
2692
2693/* ------------------------------ */
2694    .balign 64
2695.L_OP_IPUT_BYTE: /* 0x5d */
2696/* File: armv5te/OP_IPUT_BYTE.S */
2697@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2698/* File: armv5te/OP_IPUT.S */
2699    /*
2700     * General 32-bit instance field put.
2701     *
2702     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2703     */
2704    /* op vA, vB, field@CCCC */
2705    mov     r0, rINST, lsr #12          @ r0<- B
2706    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2707    FETCH(r1, 1)                        @ r1<- field ref CCCC
2708    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2709    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2710    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2711    cmp     r0, #0                      @ is resolved entry null?
2712    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27138:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2714    EXPORT_PC()                         @ resolve() could throw
2715    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2716    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2717    cmp     r0, #0                      @ success?
2718    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2719    b       common_exceptionThrown
2720
2721
2722/* ------------------------------ */
2723    .balign 64
2724.L_OP_IPUT_CHAR: /* 0x5e */
2725/* File: armv5te/OP_IPUT_CHAR.S */
2726@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2727/* File: armv5te/OP_IPUT.S */
2728    /*
2729     * General 32-bit instance field put.
2730     *
2731     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2732     */
2733    /* op vA, vB, field@CCCC */
2734    mov     r0, rINST, lsr #12          @ r0<- B
2735    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2736    FETCH(r1, 1)                        @ r1<- field ref CCCC
2737    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2738    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2739    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2740    cmp     r0, #0                      @ is resolved entry null?
2741    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27428:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2743    EXPORT_PC()                         @ resolve() could throw
2744    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2745    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2746    cmp     r0, #0                      @ success?
2747    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2748    b       common_exceptionThrown
2749
2750
2751/* ------------------------------ */
2752    .balign 64
2753.L_OP_IPUT_SHORT: /* 0x5f */
2754/* File: armv5te/OP_IPUT_SHORT.S */
2755@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2756/* File: armv5te/OP_IPUT.S */
2757    /*
2758     * General 32-bit instance field put.
2759     *
2760     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
2761     */
2762    /* op vA, vB, field@CCCC */
2763    mov     r0, rINST, lsr #12          @ r0<- B
2764    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2765    FETCH(r1, 1)                        @ r1<- field ref CCCC
2766    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2767    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2768    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2769    cmp     r0, #0                      @ is resolved entry null?
2770    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27718:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2772    EXPORT_PC()                         @ resolve() could throw
2773    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2774    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2775    cmp     r0, #0                      @ success?
2776    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2777    b       common_exceptionThrown
2778
2779
2780/* ------------------------------ */
2781    .balign 64
2782.L_OP_SGET: /* 0x60 */
2783/* File: armv5te/OP_SGET.S */
2784    /*
2785     * General 32-bit SGET handler.
2786     *
2787     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2788     */
2789    /* op vAA, field@BBBB */
2790    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2791    FETCH(r1, 1)                        @ r1<- field ref BBBB
2792    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2793    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2794    cmp     r0, #0                      @ is resolved entry null?
2795    beq     .LOP_SGET_resolve         @ yes, do resolve
2796.LOP_SGET_finish: @ field ptr in r0
2797    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2798    SMP_DMB 0                   @ acquiring load
2799    mov     r2, rINST, lsr #8           @ r2<- AA
2800    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2801    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2803    GOTO_OPCODE(ip)                     @ jump to next instruction
2804
2805/* ------------------------------ */
2806    .balign 64
2807.L_OP_SGET_WIDE: /* 0x61 */
2808/* File: armv5te/OP_SGET_WIDE.S */
2809    /*
2810     * 64-bit SGET handler.
2811     */
2812    /* sget-wide vAA, field@BBBB */
2813    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2814    FETCH(r1, 1)                        @ r1<- field ref BBBB
2815    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2816    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2817    cmp     r0, #0                      @ is resolved entry null?
2818    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2819.LOP_SGET_WIDE_finish:
2820    mov     r9, rINST, lsr #8           @ r9<- AA
2821    .if 0
2822    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2823    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2824    .else
2825    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2826    .endif
2827    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2828    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2829    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2831    GOTO_OPCODE(ip)                     @ jump to next instruction
2832
2833/* ------------------------------ */
2834    .balign 64
2835.L_OP_SGET_OBJECT: /* 0x62 */
2836/* File: armv5te/OP_SGET_OBJECT.S */
2837/* File: armv5te/OP_SGET.S */
2838    /*
2839     * General 32-bit SGET handler.
2840     *
2841     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2842     */
2843    /* op vAA, field@BBBB */
2844    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2845    FETCH(r1, 1)                        @ r1<- field ref BBBB
2846    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2847    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2848    cmp     r0, #0                      @ is resolved entry null?
2849    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2850.LOP_SGET_OBJECT_finish: @ field ptr in r0
2851    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2852    SMP_DMB 0                   @ acquiring load
2853    mov     r2, rINST, lsr #8           @ r2<- AA
2854    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2855    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2857    GOTO_OPCODE(ip)                     @ jump to next instruction
2858
2859
2860/* ------------------------------ */
2861    .balign 64
2862.L_OP_SGET_BOOLEAN: /* 0x63 */
2863/* File: armv5te/OP_SGET_BOOLEAN.S */
2864/* File: armv5te/OP_SGET.S */
2865    /*
2866     * General 32-bit SGET handler.
2867     *
2868     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2869     */
2870    /* op vAA, field@BBBB */
2871    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2872    FETCH(r1, 1)                        @ r1<- field ref BBBB
2873    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2874    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2875    cmp     r0, #0                      @ is resolved entry null?
2876    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2877.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2878    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2879    SMP_DMB 0                   @ acquiring load
2880    mov     r2, rINST, lsr #8           @ r2<- AA
2881    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2882    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2883    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2884    GOTO_OPCODE(ip)                     @ jump to next instruction
2885
2886
2887/* ------------------------------ */
2888    .balign 64
2889.L_OP_SGET_BYTE: /* 0x64 */
2890/* File: armv5te/OP_SGET_BYTE.S */
2891/* File: armv5te/OP_SGET.S */
2892    /*
2893     * General 32-bit SGET handler.
2894     *
2895     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2896     */
2897    /* op vAA, field@BBBB */
2898    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2899    FETCH(r1, 1)                        @ r1<- field ref BBBB
2900    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2901    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2902    cmp     r0, #0                      @ is resolved entry null?
2903    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2904.LOP_SGET_BYTE_finish: @ field ptr in r0
2905    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2906    SMP_DMB 0                   @ acquiring load
2907    mov     r2, rINST, lsr #8           @ r2<- AA
2908    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2909    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2911    GOTO_OPCODE(ip)                     @ jump to next instruction
2912
2913
2914/* ------------------------------ */
2915    .balign 64
2916.L_OP_SGET_CHAR: /* 0x65 */
2917/* File: armv5te/OP_SGET_CHAR.S */
2918/* File: armv5te/OP_SGET.S */
2919    /*
2920     * General 32-bit SGET handler.
2921     *
2922     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2923     */
2924    /* op vAA, field@BBBB */
2925    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2926    FETCH(r1, 1)                        @ r1<- field ref BBBB
2927    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2928    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2929    cmp     r0, #0                      @ is resolved entry null?
2930    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2931.LOP_SGET_CHAR_finish: @ field ptr in r0
2932    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2933    SMP_DMB 0                   @ acquiring load
2934    mov     r2, rINST, lsr #8           @ r2<- AA
2935    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2936    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2937    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2938    GOTO_OPCODE(ip)                     @ jump to next instruction
2939
2940
2941/* ------------------------------ */
2942    .balign 64
2943.L_OP_SGET_SHORT: /* 0x66 */
2944/* File: armv5te/OP_SGET_SHORT.S */
2945/* File: armv5te/OP_SGET.S */
2946    /*
2947     * General 32-bit SGET handler.
2948     *
2949     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2950     */
2951    /* op vAA, field@BBBB */
2952    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2953    FETCH(r1, 1)                        @ r1<- field ref BBBB
2954    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2955    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2956    cmp     r0, #0                      @ is resolved entry null?
2957    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2958.LOP_SGET_SHORT_finish: @ field ptr in r0
2959    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2960    SMP_DMB 0                   @ acquiring load
2961    mov     r2, rINST, lsr #8           @ r2<- AA
2962    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2963    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2964    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2965    GOTO_OPCODE(ip)                     @ jump to next instruction
2966
2967
2968/* ------------------------------ */
2969    .balign 64
2970.L_OP_SPUT: /* 0x67 */
2971/* File: armv5te/OP_SPUT.S */
2972    /*
2973     * General 32-bit SPUT handler.
2974     *
2975     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
2976     */
2977    /* op vAA, field@BBBB */
2978    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2979    FETCH(r1, 1)                        @ r1<- field ref BBBB
2980    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2981    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2982    cmp     r0, #0                      @ is resolved entry null?
2983    beq     .LOP_SPUT_resolve         @ yes, do resolve
2984.LOP_SPUT_finish:   @ field ptr in r0
2985    mov     r2, rINST, lsr #8           @ r2<- AA
2986    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2987    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2989    SMP_DMB 0                   @ releasing store
2990    str     r1, [r0, #offStaticField_value] @ field<- vAA
2991    GOTO_OPCODE(ip)                     @ jump to next instruction
2992
2993/* ------------------------------ */
2994    .balign 64
2995.L_OP_SPUT_WIDE: /* 0x68 */
2996/* File: armv5te/OP_SPUT_WIDE.S */
2997    /*
2998     * 64-bit SPUT handler.
2999     */
3000    /* sput-wide vAA, field@BBBB */
3001    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3002    FETCH(r1, 1)                        @ r1<- field ref BBBB
3003    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3004    mov     r9, rINST, lsr #8           @ r9<- AA
3005    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3006    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3007    cmp     r2, #0                      @ is resolved entry null?
3008    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3009.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3010    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3011    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3012    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3013    .if 0
3014    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3015    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3016    .else
3017    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3018    .endif
3019    GOTO_OPCODE(r10)                    @ jump to next instruction
3020
3021/* ------------------------------ */
3022    .balign 64
3023.L_OP_SPUT_OBJECT: /* 0x69 */
3024/* File: armv5te/OP_SPUT_OBJECT.S */
3025/* File: armv5te/OP_SPUT.S */
3026    /*
3027     * General 32-bit SPUT handler.
3028     *
3029     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3030     */
3031    /* op vAA, field@BBBB */
3032    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3033    FETCH(r1, 1)                        @ r1<- field ref BBBB
3034    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3035    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3036    cmp     r0, #0                      @ is resolved entry null?
3037    beq     .LOP_SPUT_OBJECT_resolve         @ yes, do resolve
3038.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
3039    mov     r2, rINST, lsr #8           @ r2<- AA
3040    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3041    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3043    SMP_DMB 0                   @ releasing store
3044    str     r1, [r0, #offStaticField_value] @ field<- vAA
3045    GOTO_OPCODE(ip)                     @ jump to next instruction
3046
3047
3048/* ------------------------------ */
3049    .balign 64
3050.L_OP_SPUT_BOOLEAN: /* 0x6a */
3051/* File: armv5te/OP_SPUT_BOOLEAN.S */
3052/* File: armv5te/OP_SPUT.S */
3053    /*
3054     * General 32-bit SPUT handler.
3055     *
3056     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3057     */
3058    /* op vAA, field@BBBB */
3059    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3060    FETCH(r1, 1)                        @ r1<- field ref BBBB
3061    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3062    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3063    cmp     r0, #0                      @ is resolved entry null?
3064    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3065.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3066    mov     r2, rINST, lsr #8           @ r2<- AA
3067    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3068    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3070    SMP_DMB 0                   @ releasing store
3071    str     r1, [r0, #offStaticField_value] @ field<- vAA
3072    GOTO_OPCODE(ip)                     @ jump to next instruction
3073
3074
3075/* ------------------------------ */
3076    .balign 64
3077.L_OP_SPUT_BYTE: /* 0x6b */
3078/* File: armv5te/OP_SPUT_BYTE.S */
3079/* File: armv5te/OP_SPUT.S */
3080    /*
3081     * General 32-bit SPUT handler.
3082     *
3083     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3084     */
3085    /* op vAA, field@BBBB */
3086    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3087    FETCH(r1, 1)                        @ r1<- field ref BBBB
3088    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3089    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3090    cmp     r0, #0                      @ is resolved entry null?
3091    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3092.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3093    mov     r2, rINST, lsr #8           @ r2<- AA
3094    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3095    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3096    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3097    SMP_DMB 0                   @ releasing store
3098    str     r1, [r0, #offStaticField_value] @ field<- vAA
3099    GOTO_OPCODE(ip)                     @ jump to next instruction
3100
3101
3102/* ------------------------------ */
3103    .balign 64
3104.L_OP_SPUT_CHAR: /* 0x6c */
3105/* File: armv5te/OP_SPUT_CHAR.S */
3106/* File: armv5te/OP_SPUT.S */
3107    /*
3108     * General 32-bit SPUT handler.
3109     *
3110     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3111     */
3112    /* op vAA, field@BBBB */
3113    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3114    FETCH(r1, 1)                        @ r1<- field ref BBBB
3115    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3116    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3117    cmp     r0, #0                      @ is resolved entry null?
3118    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3119.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3120    mov     r2, rINST, lsr #8           @ r2<- AA
3121    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3122    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3123    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3124    SMP_DMB 0                   @ releasing store
3125    str     r1, [r0, #offStaticField_value] @ field<- vAA
3126    GOTO_OPCODE(ip)                     @ jump to next instruction
3127
3128
3129/* ------------------------------ */
3130    .balign 64
3131.L_OP_SPUT_SHORT: /* 0x6d */
3132/* File: armv5te/OP_SPUT_SHORT.S */
3133/* File: armv5te/OP_SPUT.S */
3134    /*
3135     * General 32-bit SPUT handler.
3136     *
3137     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
3138     */
3139    /* op vAA, field@BBBB */
3140    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3141    FETCH(r1, 1)                        @ r1<- field ref BBBB
3142    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3143    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3144    cmp     r0, #0                      @ is resolved entry null?
3145    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3146.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3147    mov     r2, rINST, lsr #8           @ r2<- AA
3148    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3149    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3150    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3151    SMP_DMB 0                   @ releasing store
3152    str     r1, [r0, #offStaticField_value] @ field<- vAA
3153    GOTO_OPCODE(ip)                     @ jump to next instruction
3154
3155
3156/* ------------------------------ */
3157    .balign 64
3158.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3159/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3160    /*
3161     * Handle a virtual method call.
3162     *
3163     * for: invoke-virtual, invoke-virtual/range
3164     */
3165    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3166    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3167    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3168    FETCH(r1, 1)                        @ r1<- BBBB
3169    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3170    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3171    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3172    .if     (!0)
3173    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3174    .endif
3175    cmp     r0, #0                      @ already resolved?
3176    EXPORT_PC()                         @ must export for invoke
3177    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3178    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3179    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3180    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3181    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3182    cmp     r0, #0                      @ got null?
3183    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3184    b       common_exceptionThrown      @ yes, handle exception
3185
3186/* ------------------------------ */
3187    .balign 64
3188.L_OP_INVOKE_SUPER: /* 0x6f */
3189/* File: armv5te/OP_INVOKE_SUPER.S */
3190    /*
3191     * Handle a "super" method call.
3192     *
3193     * for: invoke-super, invoke-super/range
3194     */
3195    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3196    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3197    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3198    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3199    .if     (!0)
3200    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3201    .endif
3202    FETCH(r1, 1)                        @ r1<- BBBB
3203    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3204    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3205    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3206    cmp     r2, #0                      @ null "this"?
3207    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3208    beq     common_errNullObject        @ null "this", throw exception
3209    cmp     r0, #0                      @ already resolved?
3210    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3211    EXPORT_PC()                         @ must export for invoke
3212    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3213    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3214
3215/* ------------------------------ */
3216    .balign 64
3217.L_OP_INVOKE_DIRECT: /* 0x70 */
3218/* File: armv5te/OP_INVOKE_DIRECT.S */
3219    /*
3220     * Handle a direct method call.
3221     *
3222     * (We could defer the "is 'this' pointer null" test to the common
3223     * method invocation code, and use a flag to indicate that static
3224     * calls don't count.  If we do this as part of copying the arguments
3225     * out we could avoiding loading the first arg twice.)
3226     *
3227     * for: invoke-direct, invoke-direct/range
3228     */
3229    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3230    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3231    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3232    FETCH(r1, 1)                        @ r1<- BBBB
3233    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3234    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3235    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3236    .if     (!0)
3237    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3238    .endif
3239    cmp     r0, #0                      @ already resolved?
3240    EXPORT_PC()                         @ must export for invoke
3241    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3242    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3243.LOP_INVOKE_DIRECT_finish:
3244    cmp     r2, #0                      @ null "this" ref?
3245    bne     common_invokeMethodNoRange   @ no, continue on
3246    b       common_errNullObject        @ yes, throw exception
3247
3248/* ------------------------------ */
3249    .balign 64
3250.L_OP_INVOKE_STATIC: /* 0x71 */
3251/* File: armv5te/OP_INVOKE_STATIC.S */
3252    /*
3253     * Handle a static method call.
3254     *
3255     * for: invoke-static, invoke-static/range
3256     */
3257    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3258    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3259    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3260    FETCH(r1, 1)                        @ r1<- BBBB
3261    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3262    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3263    cmp     r0, #0                      @ already resolved?
3264    EXPORT_PC()                         @ must export for invoke
3265    bne     common_invokeMethodNoRange @ yes, continue on
32660:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3267    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3268    mov     r2, #METHOD_STATIC          @ resolver method type
3269    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3270    cmp     r0, #0                      @ got null?
3271    bne     common_invokeMethodNoRange @ no, continue
3272    b       common_exceptionThrown      @ yes, handle exception
3273
3274/* ------------------------------ */
3275    .balign 64
3276.L_OP_INVOKE_INTERFACE: /* 0x72 */
3277/* File: armv5te/OP_INVOKE_INTERFACE.S */
3278    /*
3279     * Handle an interface method call.
3280     *
3281     * for: invoke-interface, invoke-interface/range
3282     */
3283    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3284    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3285    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3286    FETCH(r1, 1)                        @ r1<- BBBB
3287    .if     (!0)
3288    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3289    .endif
3290    EXPORT_PC()                         @ must export for invoke
3291    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3292    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3293    cmp     r0, #0                      @ null obj?
3294    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3295    beq     common_errNullObject        @ yes, fail
3296    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3297    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3298    cmp     r0, #0                      @ failed?
3299    beq     common_exceptionThrown      @ yes, handle exception
3300    b       common_invokeMethodNoRange @ jump to common handler
3301
3302/* ------------------------------ */
3303    .balign 64
3304.L_OP_UNUSED_73: /* 0x73 */
3305/* File: armv5te/OP_UNUSED_73.S */
3306/* File: armv5te/unused.S */
3307    bl      common_abort
3308
3309
3310/* ------------------------------ */
3311    .balign 64
3312.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3313/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3314/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3315    /*
3316     * Handle a virtual method call.
3317     *
3318     * for: invoke-virtual, invoke-virtual/range
3319     */
3320    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3321    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3322    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3323    FETCH(r1, 1)                        @ r1<- BBBB
3324    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3325    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3326    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3327    .if     (!1)
3328    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3329    .endif
3330    cmp     r0, #0                      @ already resolved?
3331    EXPORT_PC()                         @ must export for invoke
3332    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3333    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3334    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3335    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3336    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3337    cmp     r0, #0                      @ got null?
3338    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3339    b       common_exceptionThrown      @ yes, handle exception
3340
3341
3342/* ------------------------------ */
3343    .balign 64
3344.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3345/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3346/* File: armv5te/OP_INVOKE_SUPER.S */
3347    /*
3348     * Handle a "super" method call.
3349     *
3350     * for: invoke-super, invoke-super/range
3351     */
3352    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3353    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3354    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3355    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3356    .if     (!1)
3357    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3358    .endif
3359    FETCH(r1, 1)                        @ r1<- BBBB
3360    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3361    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3362    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3363    cmp     r2, #0                      @ null "this"?
3364    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3365    beq     common_errNullObject        @ null "this", throw exception
3366    cmp     r0, #0                      @ already resolved?
3367    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3368    EXPORT_PC()                         @ must export for invoke
3369    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3370    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3371
3372
3373/* ------------------------------ */
3374    .balign 64
3375.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3376/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3377/* File: armv5te/OP_INVOKE_DIRECT.S */
3378    /*
3379     * Handle a direct method call.
3380     *
3381     * (We could defer the "is 'this' pointer null" test to the common
3382     * method invocation code, and use a flag to indicate that static
3383     * calls don't count.  If we do this as part of copying the arguments
3384     * out we could avoiding loading the first arg twice.)
3385     *
3386     * for: invoke-direct, invoke-direct/range
3387     */
3388    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3389    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3390    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3391    FETCH(r1, 1)                        @ r1<- BBBB
3392    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3393    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3394    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3395    .if     (!1)
3396    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3397    .endif
3398    cmp     r0, #0                      @ already resolved?
3399    EXPORT_PC()                         @ must export for invoke
3400    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3401    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3402.LOP_INVOKE_DIRECT_RANGE_finish:
3403    cmp     r2, #0                      @ null "this" ref?
3404    bne     common_invokeMethodRange   @ no, continue on
3405    b       common_errNullObject        @ yes, throw exception
3406
3407
3408/* ------------------------------ */
3409    .balign 64
3410.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3411/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3412/* File: armv5te/OP_INVOKE_STATIC.S */
3413    /*
3414     * Handle a static method call.
3415     *
3416     * for: invoke-static, invoke-static/range
3417     */
3418    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3419    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3420    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3421    FETCH(r1, 1)                        @ r1<- BBBB
3422    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3423    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3424    cmp     r0, #0                      @ already resolved?
3425    EXPORT_PC()                         @ must export for invoke
3426    bne     common_invokeMethodRange @ yes, continue on
34270:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3428    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3429    mov     r2, #METHOD_STATIC          @ resolver method type
3430    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3431    cmp     r0, #0                      @ got null?
3432    bne     common_invokeMethodRange @ no, continue
3433    b       common_exceptionThrown      @ yes, handle exception
3434
3435
3436/* ------------------------------ */
3437    .balign 64
3438.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3439/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3440/* File: armv5te/OP_INVOKE_INTERFACE.S */
3441    /*
3442     * Handle an interface method call.
3443     *
3444     * for: invoke-interface, invoke-interface/range
3445     */
3446    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3447    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3448    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3449    FETCH(r1, 1)                        @ r1<- BBBB
3450    .if     (!1)
3451    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3452    .endif
3453    EXPORT_PC()                         @ must export for invoke
3454    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3455    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3456    cmp     r0, #0                      @ null obj?
3457    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3458    beq     common_errNullObject        @ yes, fail
3459    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3460    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3461    cmp     r0, #0                      @ failed?
3462    beq     common_exceptionThrown      @ yes, handle exception
3463    b       common_invokeMethodRange @ jump to common handler
3464
3465
3466/* ------------------------------ */
3467    .balign 64
3468.L_OP_UNUSED_79: /* 0x79 */
3469/* File: armv5te/OP_UNUSED_79.S */
3470/* File: armv5te/unused.S */
3471    bl      common_abort
3472
3473
3474/* ------------------------------ */
3475    .balign 64
3476.L_OP_UNUSED_7A: /* 0x7a */
3477/* File: armv5te/OP_UNUSED_7A.S */
3478/* File: armv5te/unused.S */
3479    bl      common_abort
3480
3481
3482/* ------------------------------ */
3483    .balign 64
3484.L_OP_NEG_INT: /* 0x7b */
3485/* File: armv5te/OP_NEG_INT.S */
3486/* File: armv5te/unop.S */
3487    /*
3488     * Generic 32-bit unary operation.  Provide an "instr" line that
3489     * specifies an instruction that performs "result = op r0".
3490     * This could be an ARM instruction or a function call.
3491     *
3492     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3493     *      int-to-byte, int-to-char, int-to-short
3494     */
3495    /* unop vA, vB */
3496    mov     r3, rINST, lsr #12          @ r3<- B
3497    mov     r9, rINST, lsr #8           @ r9<- A+
3498    GET_VREG(r0, r3)                    @ r0<- vB
3499    and     r9, r9, #15
3500                               @ optional op; may set condition codes
3501    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3502    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3504    SET_VREG(r0, r9)                    @ vAA<- r0
3505    GOTO_OPCODE(ip)                     @ jump to next instruction
3506    /* 9-10 instructions */
3507
3508
3509/* ------------------------------ */
3510    .balign 64
3511.L_OP_NOT_INT: /* 0x7c */
3512/* File: armv5te/OP_NOT_INT.S */
3513/* File: armv5te/unop.S */
3514    /*
3515     * Generic 32-bit unary operation.  Provide an "instr" line that
3516     * specifies an instruction that performs "result = op r0".
3517     * This could be an ARM instruction or a function call.
3518     *
3519     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3520     *      int-to-byte, int-to-char, int-to-short
3521     */
3522    /* unop vA, vB */
3523    mov     r3, rINST, lsr #12          @ r3<- B
3524    mov     r9, rINST, lsr #8           @ r9<- A+
3525    GET_VREG(r0, r3)                    @ r0<- vB
3526    and     r9, r9, #15
3527                               @ optional op; may set condition codes
3528    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3529    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3530    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3531    SET_VREG(r0, r9)                    @ vAA<- r0
3532    GOTO_OPCODE(ip)                     @ jump to next instruction
3533    /* 9-10 instructions */
3534
3535
3536/* ------------------------------ */
3537    .balign 64
3538.L_OP_NEG_LONG: /* 0x7d */
3539/* File: armv5te/OP_NEG_LONG.S */
3540/* File: armv5te/unopWide.S */
3541    /*
3542     * Generic 64-bit unary operation.  Provide an "instr" line that
3543     * specifies an instruction that performs "result = op r0/r1".
3544     * This could be an ARM instruction or a function call.
3545     *
3546     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3547     */
3548    /* unop vA, vB */
3549    mov     r9, rINST, lsr #8           @ r9<- A+
3550    mov     r3, rINST, lsr #12          @ r3<- B
3551    and     r9, r9, #15
3552    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3553    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3554    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3555    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3556    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3557    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3559    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3560    GOTO_OPCODE(ip)                     @ jump to next instruction
3561    /* 12-13 instructions */
3562
3563
3564/* ------------------------------ */
3565    .balign 64
3566.L_OP_NOT_LONG: /* 0x7e */
3567/* File: armv5te/OP_NOT_LONG.S */
3568/* File: armv5te/unopWide.S */
3569    /*
3570     * Generic 64-bit unary operation.  Provide an "instr" line that
3571     * specifies an instruction that performs "result = op r0/r1".
3572     * This could be an ARM instruction or a function call.
3573     *
3574     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3575     */
3576    /* unop vA, vB */
3577    mov     r9, rINST, lsr #8           @ r9<- A+
3578    mov     r3, rINST, lsr #12          @ r3<- B
3579    and     r9, r9, #15
3580    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3581    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3582    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3583    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3584    mvn     r0, r0                           @ optional op; may set condition codes
3585    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3587    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3588    GOTO_OPCODE(ip)                     @ jump to next instruction
3589    /* 12-13 instructions */
3590
3591
3592/* ------------------------------ */
3593    .balign 64
3594.L_OP_NEG_FLOAT: /* 0x7f */
3595/* File: armv5te/OP_NEG_FLOAT.S */
3596/* File: armv5te/unop.S */
3597    /*
3598     * Generic 32-bit unary operation.  Provide an "instr" line that
3599     * specifies an instruction that performs "result = op r0".
3600     * This could be an ARM instruction or a function call.
3601     *
3602     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3603     *      int-to-byte, int-to-char, int-to-short
3604     */
3605    /* unop vA, vB */
3606    mov     r3, rINST, lsr #12          @ r3<- B
3607    mov     r9, rINST, lsr #8           @ r9<- A+
3608    GET_VREG(r0, r3)                    @ r0<- vB
3609    and     r9, r9, #15
3610                               @ optional op; may set condition codes
3611    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3612    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3614    SET_VREG(r0, r9)                    @ vAA<- r0
3615    GOTO_OPCODE(ip)                     @ jump to next instruction
3616    /* 9-10 instructions */
3617
3618
3619/* ------------------------------ */
3620    .balign 64
3621.L_OP_NEG_DOUBLE: /* 0x80 */
3622/* File: armv5te/OP_NEG_DOUBLE.S */
3623/* File: armv5te/unopWide.S */
3624    /*
3625     * Generic 64-bit unary operation.  Provide an "instr" line that
3626     * specifies an instruction that performs "result = op r0/r1".
3627     * This could be an ARM instruction or a function call.
3628     *
3629     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3630     */
3631    /* unop vA, vB */
3632    mov     r9, rINST, lsr #8           @ r9<- A+
3633    mov     r3, rINST, lsr #12          @ r3<- B
3634    and     r9, r9, #15
3635    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3636    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3637    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3638    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3639                               @ optional op; may set condition codes
3640    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3642    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3643    GOTO_OPCODE(ip)                     @ jump to next instruction
3644    /* 12-13 instructions */
3645
3646
3647/* ------------------------------ */
3648    .balign 64
3649.L_OP_INT_TO_LONG: /* 0x81 */
3650/* File: armv5te/OP_INT_TO_LONG.S */
3651/* File: armv5te/unopWider.S */
3652    /*
3653     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3654     * that specifies an instruction that performs "result = op r0", where
3655     * "result" is a 64-bit quantity in r0/r1.
3656     *
3657     * For: int-to-long, int-to-double, float-to-long, float-to-double
3658     */
3659    /* unop vA, vB */
3660    mov     r9, rINST, lsr #8           @ r9<- A+
3661    mov     r3, rINST, lsr #12          @ r3<- B
3662    and     r9, r9, #15
3663    GET_VREG(r0, r3)                    @ r0<- vB
3664    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3665                               @ optional op; may set condition codes
3666    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3667    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3668    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3669    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3670    GOTO_OPCODE(ip)                     @ jump to next instruction
3671    /* 10-11 instructions */
3672
3673
3674/* ------------------------------ */
3675    .balign 64
3676.L_OP_INT_TO_FLOAT: /* 0x82 */
3677/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3678/* File: arm-vfp/funop.S */
3679    /*
3680     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3681     * line that specifies an instruction that performs "s1 = op s0".
3682     *
3683     * for: int-to-float, float-to-int
3684     */
3685    /* unop vA, vB */
3686    mov     r3, rINST, lsr #12          @ r3<- B
3687    mov     r9, rINST, lsr #8           @ r9<- A+
3688    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3689    flds    s0, [r3]                    @ s0<- vB
3690    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3691    and     r9, r9, #15                 @ r9<- A
3692    fsitos  s1, s0                              @ s1<- op
3693    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3694    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3695    fsts    s1, [r9]                    @ vA<- s1
3696    GOTO_OPCODE(ip)                     @ jump to next instruction
3697
3698
3699/* ------------------------------ */
3700    .balign 64
3701.L_OP_INT_TO_DOUBLE: /* 0x83 */
3702/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3703/* File: arm-vfp/funopWider.S */
3704    /*
3705     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3706     * "instr" line that specifies an instruction that performs "d0 = op s0".
3707     *
3708     * For: int-to-double, float-to-double
3709     */
3710    /* unop vA, vB */
3711    mov     r3, rINST, lsr #12          @ r3<- B
3712    mov     r9, rINST, lsr #8           @ r9<- A+
3713    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3714    flds    s0, [r3]                    @ s0<- vB
3715    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3716    and     r9, r9, #15                 @ r9<- A
3717    fsitod  d0, s0                              @ d0<- op
3718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3719    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3720    fstd    d0, [r9]                    @ vA<- d0
3721    GOTO_OPCODE(ip)                     @ jump to next instruction
3722
3723
3724/* ------------------------------ */
3725    .balign 64
3726.L_OP_LONG_TO_INT: /* 0x84 */
3727/* File: armv5te/OP_LONG_TO_INT.S */
3728/* we ignore the high word, making this equivalent to a 32-bit reg move */
3729/* File: armv5te/OP_MOVE.S */
3730    /* for move, move-object, long-to-int */
3731    /* op vA, vB */
3732    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3733    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3734    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3735    GET_VREG(r2, r1)                    @ r2<- fp[B]
3736    and     r0, r0, #15
3737    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3738    SET_VREG(r2, r0)                    @ fp[A]<- r2
3739    GOTO_OPCODE(ip)                     @ execute next instruction
3740
3741
3742/* ------------------------------ */
3743    .balign 64
3744.L_OP_LONG_TO_FLOAT: /* 0x85 */
3745/* File: armv5te/OP_LONG_TO_FLOAT.S */
3746/* File: armv5te/unopNarrower.S */
3747    /*
3748     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3749     * that specifies an instruction that performs "result = op r0/r1", where
3750     * "result" is a 32-bit quantity in r0.
3751     *
3752     * For: long-to-float, double-to-int, double-to-float
3753     *
3754     * (This would work for long-to-int, but that instruction is actually
3755     * an exact match for OP_MOVE.)
3756     */
3757    /* unop vA, vB */
3758    mov     r3, rINST, lsr #12          @ r3<- B
3759    mov     r9, rINST, lsr #8           @ r9<- A+
3760    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3761    and     r9, r9, #15
3762    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3763    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3764                               @ optional op; may set condition codes
3765    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3766    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3767    SET_VREG(r0, r9)                    @ vA<- r0
3768    GOTO_OPCODE(ip)                     @ jump to next instruction
3769    /* 10-11 instructions */
3770
3771
3772/* ------------------------------ */
3773    .balign 64
3774.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3775/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3776/* File: armv5te/unopWide.S */
3777    /*
3778     * Generic 64-bit unary operation.  Provide an "instr" line that
3779     * specifies an instruction that performs "result = op r0/r1".
3780     * This could be an ARM instruction or a function call.
3781     *
3782     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3783     */
3784    /* unop vA, vB */
3785    mov     r9, rINST, lsr #8           @ r9<- A+
3786    mov     r3, rINST, lsr #12          @ r3<- B
3787    and     r9, r9, #15
3788    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3789    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3790    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3791    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3792                               @ optional op; may set condition codes
3793    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3795    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3796    GOTO_OPCODE(ip)                     @ jump to next instruction
3797    /* 12-13 instructions */
3798
3799
3800/* ------------------------------ */
3801    .balign 64
3802.L_OP_FLOAT_TO_INT: /* 0x87 */
3803/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3804/* File: arm-vfp/funop.S */
3805    /*
3806     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3807     * line that specifies an instruction that performs "s1 = op s0".
3808     *
3809     * for: int-to-float, float-to-int
3810     */
3811    /* unop vA, vB */
3812    mov     r3, rINST, lsr #12          @ r3<- B
3813    mov     r9, rINST, lsr #8           @ r9<- A+
3814    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3815    flds    s0, [r3]                    @ s0<- vB
3816    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3817    and     r9, r9, #15                 @ r9<- A
3818    ftosizs s1, s0                              @ s1<- op
3819    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3820    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3821    fsts    s1, [r9]                    @ vA<- s1
3822    GOTO_OPCODE(ip)                     @ jump to next instruction
3823
3824
3825/* ------------------------------ */
3826    .balign 64
3827.L_OP_FLOAT_TO_LONG: /* 0x88 */
3828/* File: armv5te/OP_FLOAT_TO_LONG.S */
3829@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3830/* File: armv5te/unopWider.S */
3831    /*
3832     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3833     * that specifies an instruction that performs "result = op r0", where
3834     * "result" is a 64-bit quantity in r0/r1.
3835     *
3836     * For: int-to-long, int-to-double, float-to-long, float-to-double
3837     */
3838    /* unop vA, vB */
3839    mov     r9, rINST, lsr #8           @ r9<- A+
3840    mov     r3, rINST, lsr #12          @ r3<- B
3841    and     r9, r9, #15
3842    GET_VREG(r0, r3)                    @ r0<- vB
3843    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3844                               @ optional op; may set condition codes
3845    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3846    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3847    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3848    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3849    GOTO_OPCODE(ip)                     @ jump to next instruction
3850    /* 10-11 instructions */
3851
3852
3853
3854/* ------------------------------ */
3855    .balign 64
3856.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3857/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3858/* File: arm-vfp/funopWider.S */
3859    /*
3860     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3861     * "instr" line that specifies an instruction that performs "d0 = op s0".
3862     *
3863     * For: int-to-double, float-to-double
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    flds    s0, [r3]                    @ s0<- vB
3870    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3871    and     r9, r9, #15                 @ r9<- A
3872    fcvtds  d0, s0                              @ d0<- op
3873    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3874    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3875    fstd    d0, [r9]                    @ vA<- d0
3876    GOTO_OPCODE(ip)                     @ jump to next instruction
3877
3878
3879/* ------------------------------ */
3880    .balign 64
3881.L_OP_DOUBLE_TO_INT: /* 0x8a */
3882/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3883/* File: arm-vfp/funopNarrower.S */
3884    /*
3885     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3886     * "instr" line that specifies an instruction that performs "s0 = op d0".
3887     *
3888     * For: double-to-int, double-to-float
3889     */
3890    /* unop vA, vB */
3891    mov     r3, rINST, lsr #12          @ r3<- B
3892    mov     r9, rINST, lsr #8           @ r9<- A+
3893    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3894    fldd    d0, [r3]                    @ d0<- vB
3895    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3896    and     r9, r9, #15                 @ r9<- A
3897    ftosizd  s0, d0                              @ s0<- op
3898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3899    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3900    fsts    s0, [r9]                    @ vA<- s0
3901    GOTO_OPCODE(ip)                     @ jump to next instruction
3902
3903
3904/* ------------------------------ */
3905    .balign 64
3906.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3907/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3908@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3909/* File: armv5te/unopWide.S */
3910    /*
3911     * Generic 64-bit unary operation.  Provide an "instr" line that
3912     * specifies an instruction that performs "result = op r0/r1".
3913     * This could be an ARM instruction or a function call.
3914     *
3915     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3916     */
3917    /* unop vA, vB */
3918    mov     r9, rINST, lsr #8           @ r9<- A+
3919    mov     r3, rINST, lsr #12          @ r3<- B
3920    and     r9, r9, #15
3921    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3922    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3923    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3924    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3925                               @ optional op; may set condition codes
3926    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3928    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3929    GOTO_OPCODE(ip)                     @ jump to next instruction
3930    /* 12-13 instructions */
3931
3932
3933
3934/* ------------------------------ */
3935    .balign 64
3936.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3937/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3938/* File: arm-vfp/funopNarrower.S */
3939    /*
3940     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3941     * "instr" line that specifies an instruction that performs "s0 = op d0".
3942     *
3943     * For: double-to-int, double-to-float
3944     */
3945    /* unop vA, vB */
3946    mov     r3, rINST, lsr #12          @ r3<- B
3947    mov     r9, rINST, lsr #8           @ r9<- A+
3948    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3949    fldd    d0, [r3]                    @ d0<- vB
3950    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3951    and     r9, r9, #15                 @ r9<- A
3952    fcvtsd  s0, d0                              @ s0<- op
3953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3954    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3955    fsts    s0, [r9]                    @ vA<- s0
3956    GOTO_OPCODE(ip)                     @ jump to next instruction
3957
3958
3959/* ------------------------------ */
3960    .balign 64
3961.L_OP_INT_TO_BYTE: /* 0x8d */
3962/* File: armv5te/OP_INT_TO_BYTE.S */
3963/* File: armv5te/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    mov     r9, rINST, lsr #8           @ r9<- A+
3975    GET_VREG(r0, r3)                    @ r0<- vB
3976    and     r9, r9, #15
3977    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3978    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3979    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3980    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3981    SET_VREG(r0, r9)                    @ vAA<- r0
3982    GOTO_OPCODE(ip)                     @ jump to next instruction
3983    /* 9-10 instructions */
3984
3985
3986/* ------------------------------ */
3987    .balign 64
3988.L_OP_INT_TO_CHAR: /* 0x8e */
3989/* File: armv5te/OP_INT_TO_CHAR.S */
3990/* File: armv5te/unop.S */
3991    /*
3992     * Generic 32-bit unary operation.  Provide an "instr" line that
3993     * specifies an instruction that performs "result = op r0".
3994     * This could be an ARM instruction or a function call.
3995     *
3996     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3997     *      int-to-byte, int-to-char, int-to-short
3998     */
3999    /* unop vA, vB */
4000    mov     r3, rINST, lsr #12          @ r3<- B
4001    mov     r9, rINST, lsr #8           @ r9<- A+
4002    GET_VREG(r0, r3)                    @ r0<- vB
4003    and     r9, r9, #15
4004    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4005    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4006    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4007    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4008    SET_VREG(r0, r9)                    @ vAA<- r0
4009    GOTO_OPCODE(ip)                     @ jump to next instruction
4010    /* 9-10 instructions */
4011
4012
4013/* ------------------------------ */
4014    .balign 64
4015.L_OP_INT_TO_SHORT: /* 0x8f */
4016/* File: armv5te/OP_INT_TO_SHORT.S */
4017/* File: armv5te/unop.S */
4018    /*
4019     * Generic 32-bit unary operation.  Provide an "instr" line that
4020     * specifies an instruction that performs "result = op r0".
4021     * This could be an ARM instruction or a function call.
4022     *
4023     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4024     *      int-to-byte, int-to-char, int-to-short
4025     */
4026    /* unop vA, vB */
4027    mov     r3, rINST, lsr #12          @ r3<- B
4028    mov     r9, rINST, lsr #8           @ r9<- A+
4029    GET_VREG(r0, r3)                    @ r0<- vB
4030    and     r9, r9, #15
4031    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4032    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4033    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4034    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4035    SET_VREG(r0, r9)                    @ vAA<- r0
4036    GOTO_OPCODE(ip)                     @ jump to next instruction
4037    /* 9-10 instructions */
4038
4039
4040/* ------------------------------ */
4041    .balign 64
4042.L_OP_ADD_INT: /* 0x90 */
4043/* File: armv5te/OP_ADD_INT.S */
4044/* File: armv5te/binop.S */
4045    /*
4046     * Generic 32-bit binary operation.  Provide an "instr" line that
4047     * specifies an instruction that performs "result = r0 op r1".
4048     * This could be an ARM instruction or a function call.  (If the result
4049     * comes back in a register other than r0, you can override "result".)
4050     *
4051     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4052     * vCC (r1).  Useful for integer division and modulus.  Note that we
4053     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4054     * handles it correctly.
4055     *
4056     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4057     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4058     *      mul-float, div-float, rem-float
4059     */
4060    /* binop vAA, vBB, vCC */
4061    FETCH(r0, 1)                        @ r0<- CCBB
4062    mov     r9, rINST, lsr #8           @ r9<- AA
4063    mov     r3, r0, lsr #8              @ r3<- CC
4064    and     r2, r0, #255                @ r2<- BB
4065    GET_VREG(r1, r3)                    @ r1<- vCC
4066    GET_VREG(r0, r2)                    @ r0<- vBB
4067    .if 0
4068    cmp     r1, #0                      @ is second operand zero?
4069    beq     common_errDivideByZero
4070    .endif
4071
4072    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4073                               @ optional op; may set condition codes
4074    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4075    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4076    SET_VREG(r0, r9)               @ vAA<- r0
4077    GOTO_OPCODE(ip)                     @ jump to next instruction
4078    /* 11-14 instructions */
4079
4080
4081/* ------------------------------ */
4082    .balign 64
4083.L_OP_SUB_INT: /* 0x91 */
4084/* File: armv5te/OP_SUB_INT.S */
4085/* File: armv5te/binop.S */
4086    /*
4087     * Generic 32-bit binary operation.  Provide an "instr" line that
4088     * specifies an instruction that performs "result = r0 op r1".
4089     * This could be an ARM instruction or a function call.  (If the result
4090     * comes back in a register other than r0, you can override "result".)
4091     *
4092     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4093     * vCC (r1).  Useful for integer division and modulus.  Note that we
4094     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4095     * handles it correctly.
4096     *
4097     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4098     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4099     *      mul-float, div-float, rem-float
4100     */
4101    /* binop vAA, vBB, vCC */
4102    FETCH(r0, 1)                        @ r0<- CCBB
4103    mov     r9, rINST, lsr #8           @ r9<- AA
4104    mov     r3, r0, lsr #8              @ r3<- CC
4105    and     r2, r0, #255                @ r2<- BB
4106    GET_VREG(r1, r3)                    @ r1<- vCC
4107    GET_VREG(r0, r2)                    @ r0<- vBB
4108    .if 0
4109    cmp     r1, #0                      @ is second operand zero?
4110    beq     common_errDivideByZero
4111    .endif
4112
4113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4114                               @ optional op; may set condition codes
4115    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4117    SET_VREG(r0, r9)               @ vAA<- r0
4118    GOTO_OPCODE(ip)                     @ jump to next instruction
4119    /* 11-14 instructions */
4120
4121
4122/* ------------------------------ */
4123    .balign 64
4124.L_OP_MUL_INT: /* 0x92 */
4125/* File: armv5te/OP_MUL_INT.S */
4126/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4127/* File: armv5te/binop.S */
4128    /*
4129     * Generic 32-bit binary operation.  Provide an "instr" line that
4130     * specifies an instruction that performs "result = r0 op r1".
4131     * This could be an ARM instruction or a function call.  (If the result
4132     * comes back in a register other than r0, you can override "result".)
4133     *
4134     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4135     * vCC (r1).  Useful for integer division and modulus.  Note that we
4136     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4137     * handles it correctly.
4138     *
4139     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4140     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4141     *      mul-float, div-float, rem-float
4142     */
4143    /* binop vAA, vBB, vCC */
4144    FETCH(r0, 1)                        @ r0<- CCBB
4145    mov     r9, rINST, lsr #8           @ r9<- AA
4146    mov     r3, r0, lsr #8              @ r3<- CC
4147    and     r2, r0, #255                @ r2<- BB
4148    GET_VREG(r1, r3)                    @ r1<- vCC
4149    GET_VREG(r0, r2)                    @ r0<- vBB
4150    .if 0
4151    cmp     r1, #0                      @ is second operand zero?
4152    beq     common_errDivideByZero
4153    .endif
4154
4155    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4156                               @ optional op; may set condition codes
4157    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4159    SET_VREG(r0, r9)               @ vAA<- r0
4160    GOTO_OPCODE(ip)                     @ jump to next instruction
4161    /* 11-14 instructions */
4162
4163
4164/* ------------------------------ */
4165    .balign 64
4166.L_OP_DIV_INT: /* 0x93 */
4167/* File: armv5te/OP_DIV_INT.S */
4168/* File: armv5te/binop.S */
4169    /*
4170     * Generic 32-bit binary operation.  Provide an "instr" line that
4171     * specifies an instruction that performs "result = r0 op r1".
4172     * This could be an ARM instruction or a function call.  (If the result
4173     * comes back in a register other than r0, you can override "result".)
4174     *
4175     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4176     * vCC (r1).  Useful for integer division and modulus.  Note that we
4177     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4178     * handles it correctly.
4179     *
4180     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4181     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4182     *      mul-float, div-float, rem-float
4183     */
4184    /* binop vAA, vBB, vCC */
4185    FETCH(r0, 1)                        @ r0<- CCBB
4186    mov     r9, rINST, lsr #8           @ r9<- AA
4187    mov     r3, r0, lsr #8              @ r3<- CC
4188    and     r2, r0, #255                @ r2<- BB
4189    GET_VREG(r1, r3)                    @ r1<- vCC
4190    GET_VREG(r0, r2)                    @ r0<- vBB
4191    .if 1
4192    cmp     r1, #0                      @ is second operand zero?
4193    beq     common_errDivideByZero
4194    .endif
4195
4196    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4197                               @ optional op; may set condition codes
4198    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4199    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4200    SET_VREG(r0, r9)               @ vAA<- r0
4201    GOTO_OPCODE(ip)                     @ jump to next instruction
4202    /* 11-14 instructions */
4203
4204
4205/* ------------------------------ */
4206    .balign 64
4207.L_OP_REM_INT: /* 0x94 */
4208/* File: armv5te/OP_REM_INT.S */
4209/* idivmod returns quotient in r0 and remainder in r1 */
4210/* File: armv5te/binop.S */
4211    /*
4212     * Generic 32-bit binary operation.  Provide an "instr" line that
4213     * specifies an instruction that performs "result = r0 op r1".
4214     * This could be an ARM instruction or a function call.  (If the result
4215     * comes back in a register other than r0, you can override "result".)
4216     *
4217     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4218     * vCC (r1).  Useful for integer division and modulus.  Note that we
4219     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4220     * handles it correctly.
4221     *
4222     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4223     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4224     *      mul-float, div-float, rem-float
4225     */
4226    /* binop vAA, vBB, vCC */
4227    FETCH(r0, 1)                        @ r0<- CCBB
4228    mov     r9, rINST, lsr #8           @ r9<- AA
4229    mov     r3, r0, lsr #8              @ r3<- CC
4230    and     r2, r0, #255                @ r2<- BB
4231    GET_VREG(r1, r3)                    @ r1<- vCC
4232    GET_VREG(r0, r2)                    @ r0<- vBB
4233    .if 1
4234    cmp     r1, #0                      @ is second operand zero?
4235    beq     common_errDivideByZero
4236    .endif
4237
4238    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4239                               @ optional op; may set condition codes
4240    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4241    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4242    SET_VREG(r1, r9)               @ vAA<- r1
4243    GOTO_OPCODE(ip)                     @ jump to next instruction
4244    /* 11-14 instructions */
4245
4246
4247/* ------------------------------ */
4248    .balign 64
4249.L_OP_AND_INT: /* 0x95 */
4250/* File: armv5te/OP_AND_INT.S */
4251/* File: armv5te/binop.S */
4252    /*
4253     * Generic 32-bit binary operation.  Provide an "instr" line that
4254     * specifies an instruction that performs "result = r0 op r1".
4255     * This could be an ARM instruction or a function call.  (If the result
4256     * comes back in a register other than r0, you can override "result".)
4257     *
4258     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4259     * vCC (r1).  Useful for integer division and modulus.  Note that we
4260     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4261     * handles it correctly.
4262     *
4263     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4264     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4265     *      mul-float, div-float, rem-float
4266     */
4267    /* binop vAA, vBB, vCC */
4268    FETCH(r0, 1)                        @ r0<- CCBB
4269    mov     r9, rINST, lsr #8           @ r9<- AA
4270    mov     r3, r0, lsr #8              @ r3<- CC
4271    and     r2, r0, #255                @ r2<- BB
4272    GET_VREG(r1, r3)                    @ r1<- vCC
4273    GET_VREG(r0, r2)                    @ r0<- vBB
4274    .if 0
4275    cmp     r1, #0                      @ is second operand zero?
4276    beq     common_errDivideByZero
4277    .endif
4278
4279    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4280                               @ optional op; may set condition codes
4281    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4282    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4283    SET_VREG(r0, r9)               @ vAA<- r0
4284    GOTO_OPCODE(ip)                     @ jump to next instruction
4285    /* 11-14 instructions */
4286
4287
4288/* ------------------------------ */
4289    .balign 64
4290.L_OP_OR_INT: /* 0x96 */
4291/* File: armv5te/OP_OR_INT.S */
4292/* File: armv5te/binop.S */
4293    /*
4294     * Generic 32-bit binary operation.  Provide an "instr" line that
4295     * specifies an instruction that performs "result = r0 op r1".
4296     * This could be an ARM instruction or a function call.  (If the result
4297     * comes back in a register other than r0, you can override "result".)
4298     *
4299     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4300     * vCC (r1).  Useful for integer division and modulus.  Note that we
4301     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4302     * handles it correctly.
4303     *
4304     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4305     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4306     *      mul-float, div-float, rem-float
4307     */
4308    /* binop vAA, vBB, vCC */
4309    FETCH(r0, 1)                        @ r0<- CCBB
4310    mov     r9, rINST, lsr #8           @ r9<- AA
4311    mov     r3, r0, lsr #8              @ r3<- CC
4312    and     r2, r0, #255                @ r2<- BB
4313    GET_VREG(r1, r3)                    @ r1<- vCC
4314    GET_VREG(r0, r2)                    @ r0<- vBB
4315    .if 0
4316    cmp     r1, #0                      @ is second operand zero?
4317    beq     common_errDivideByZero
4318    .endif
4319
4320    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4321                               @ optional op; may set condition codes
4322    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4323    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4324    SET_VREG(r0, r9)               @ vAA<- r0
4325    GOTO_OPCODE(ip)                     @ jump to next instruction
4326    /* 11-14 instructions */
4327
4328
4329/* ------------------------------ */
4330    .balign 64
4331.L_OP_XOR_INT: /* 0x97 */
4332/* File: armv5te/OP_XOR_INT.S */
4333/* File: armv5te/binop.S */
4334    /*
4335     * Generic 32-bit binary operation.  Provide an "instr" line that
4336     * specifies an instruction that performs "result = r0 op r1".
4337     * This could be an ARM instruction or a function call.  (If the result
4338     * comes back in a register other than r0, you can override "result".)
4339     *
4340     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4341     * vCC (r1).  Useful for integer division and modulus.  Note that we
4342     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4343     * handles it correctly.
4344     *
4345     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4346     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4347     *      mul-float, div-float, rem-float
4348     */
4349    /* binop vAA, vBB, vCC */
4350    FETCH(r0, 1)                        @ r0<- CCBB
4351    mov     r9, rINST, lsr #8           @ r9<- AA
4352    mov     r3, r0, lsr #8              @ r3<- CC
4353    and     r2, r0, #255                @ r2<- BB
4354    GET_VREG(r1, r3)                    @ r1<- vCC
4355    GET_VREG(r0, r2)                    @ r0<- vBB
4356    .if 0
4357    cmp     r1, #0                      @ is second operand zero?
4358    beq     common_errDivideByZero
4359    .endif
4360
4361    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4362                               @ optional op; may set condition codes
4363    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4364    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4365    SET_VREG(r0, r9)               @ vAA<- r0
4366    GOTO_OPCODE(ip)                     @ jump to next instruction
4367    /* 11-14 instructions */
4368
4369
4370/* ------------------------------ */
4371    .balign 64
4372.L_OP_SHL_INT: /* 0x98 */
4373/* File: armv5te/OP_SHL_INT.S */
4374/* File: armv5te/binop.S */
4375    /*
4376     * Generic 32-bit binary operation.  Provide an "instr" line that
4377     * specifies an instruction that performs "result = r0 op r1".
4378     * This could be an ARM instruction or a function call.  (If the result
4379     * comes back in a register other than r0, you can override "result".)
4380     *
4381     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4382     * vCC (r1).  Useful for integer division and modulus.  Note that we
4383     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4384     * handles it correctly.
4385     *
4386     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4387     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4388     *      mul-float, div-float, rem-float
4389     */
4390    /* binop vAA, vBB, vCC */
4391    FETCH(r0, 1)                        @ r0<- CCBB
4392    mov     r9, rINST, lsr #8           @ r9<- AA
4393    mov     r3, r0, lsr #8              @ r3<- CC
4394    and     r2, r0, #255                @ r2<- BB
4395    GET_VREG(r1, r3)                    @ r1<- vCC
4396    GET_VREG(r0, r2)                    @ r0<- vBB
4397    .if 0
4398    cmp     r1, #0                      @ is second operand zero?
4399    beq     common_errDivideByZero
4400    .endif
4401
4402    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4403    and     r1, r1, #31                           @ optional op; may set condition codes
4404    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4405    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4406    SET_VREG(r0, r9)               @ vAA<- r0
4407    GOTO_OPCODE(ip)                     @ jump to next instruction
4408    /* 11-14 instructions */
4409
4410
4411/* ------------------------------ */
4412    .balign 64
4413.L_OP_SHR_INT: /* 0x99 */
4414/* File: armv5te/OP_SHR_INT.S */
4415/* File: armv5te/binop.S */
4416    /*
4417     * Generic 32-bit binary operation.  Provide an "instr" line that
4418     * specifies an instruction that performs "result = r0 op r1".
4419     * This could be an ARM instruction or a function call.  (If the result
4420     * comes back in a register other than r0, you can override "result".)
4421     *
4422     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4423     * vCC (r1).  Useful for integer division and modulus.  Note that we
4424     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4425     * handles it correctly.
4426     *
4427     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4428     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4429     *      mul-float, div-float, rem-float
4430     */
4431    /* binop vAA, vBB, vCC */
4432    FETCH(r0, 1)                        @ r0<- CCBB
4433    mov     r9, rINST, lsr #8           @ r9<- AA
4434    mov     r3, r0, lsr #8              @ r3<- CC
4435    and     r2, r0, #255                @ r2<- BB
4436    GET_VREG(r1, r3)                    @ r1<- vCC
4437    GET_VREG(r0, r2)                    @ r0<- vBB
4438    .if 0
4439    cmp     r1, #0                      @ is second operand zero?
4440    beq     common_errDivideByZero
4441    .endif
4442
4443    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4444    and     r1, r1, #31                           @ optional op; may set condition codes
4445    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4446    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4447    SET_VREG(r0, r9)               @ vAA<- r0
4448    GOTO_OPCODE(ip)                     @ jump to next instruction
4449    /* 11-14 instructions */
4450
4451
4452/* ------------------------------ */
4453    .balign 64
4454.L_OP_USHR_INT: /* 0x9a */
4455/* File: armv5te/OP_USHR_INT.S */
4456/* File: armv5te/binop.S */
4457    /*
4458     * Generic 32-bit binary operation.  Provide an "instr" line that
4459     * specifies an instruction that performs "result = r0 op r1".
4460     * This could be an ARM instruction or a function call.  (If the result
4461     * comes back in a register other than r0, you can override "result".)
4462     *
4463     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4464     * vCC (r1).  Useful for integer division and modulus.  Note that we
4465     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4466     * handles it correctly.
4467     *
4468     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4469     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4470     *      mul-float, div-float, rem-float
4471     */
4472    /* binop vAA, vBB, vCC */
4473    FETCH(r0, 1)                        @ r0<- CCBB
4474    mov     r9, rINST, lsr #8           @ r9<- AA
4475    mov     r3, r0, lsr #8              @ r3<- CC
4476    and     r2, r0, #255                @ r2<- BB
4477    GET_VREG(r1, r3)                    @ r1<- vCC
4478    GET_VREG(r0, r2)                    @ r0<- vBB
4479    .if 0
4480    cmp     r1, #0                      @ is second operand zero?
4481    beq     common_errDivideByZero
4482    .endif
4483
4484    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4485    and     r1, r1, #31                           @ optional op; may set condition codes
4486    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4488    SET_VREG(r0, r9)               @ vAA<- r0
4489    GOTO_OPCODE(ip)                     @ jump to next instruction
4490    /* 11-14 instructions */
4491
4492
4493/* ------------------------------ */
4494    .balign 64
4495.L_OP_ADD_LONG: /* 0x9b */
4496/* File: armv5te/OP_ADD_LONG.S */
4497/* File: armv5te/binopWide.S */
4498    /*
4499     * Generic 64-bit binary operation.  Provide an "instr" line that
4500     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4501     * This could be an ARM instruction or a function call.  (If the result
4502     * comes back in a register other than r0, you can override "result".)
4503     *
4504     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4505     * vCC (r1).  Useful for integer division and modulus.
4506     *
4507     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4508     *      xor-long, add-double, sub-double, mul-double, div-double,
4509     *      rem-double
4510     *
4511     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4512     */
4513    /* binop vAA, vBB, vCC */
4514    FETCH(r0, 1)                        @ r0<- CCBB
4515    mov     r9, rINST, lsr #8           @ r9<- AA
4516    and     r2, r0, #255                @ r2<- BB
4517    mov     r3, r0, lsr #8              @ r3<- CC
4518    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4519    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4520    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4521    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4522    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4523    .if 0
4524    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4525    beq     common_errDivideByZero
4526    .endif
4527    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4528
4529    adds    r0, r0, r2                           @ optional op; may set condition codes
4530    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4532    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4533    GOTO_OPCODE(ip)                     @ jump to next instruction
4534    /* 14-17 instructions */
4535
4536
4537/* ------------------------------ */
4538    .balign 64
4539.L_OP_SUB_LONG: /* 0x9c */
4540/* File: armv5te/OP_SUB_LONG.S */
4541/* File: armv5te/binopWide.S */
4542    /*
4543     * Generic 64-bit binary operation.  Provide an "instr" line that
4544     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4545     * This could be an ARM instruction or a function call.  (If the result
4546     * comes back in a register other than r0, you can override "result".)
4547     *
4548     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4549     * vCC (r1).  Useful for integer division and modulus.
4550     *
4551     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4552     *      xor-long, add-double, sub-double, mul-double, div-double,
4553     *      rem-double
4554     *
4555     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4556     */
4557    /* binop vAA, vBB, vCC */
4558    FETCH(r0, 1)                        @ r0<- CCBB
4559    mov     r9, rINST, lsr #8           @ r9<- AA
4560    and     r2, r0, #255                @ r2<- BB
4561    mov     r3, r0, lsr #8              @ r3<- CC
4562    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4563    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4564    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4565    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4566    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4567    .if 0
4568    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4569    beq     common_errDivideByZero
4570    .endif
4571    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4572
4573    subs    r0, r0, r2                           @ optional op; may set condition codes
4574    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4575    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4576    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4577    GOTO_OPCODE(ip)                     @ jump to next instruction
4578    /* 14-17 instructions */
4579
4580
4581/* ------------------------------ */
4582    .balign 64
4583.L_OP_MUL_LONG: /* 0x9d */
4584/* File: armv5te/OP_MUL_LONG.S */
4585    /*
4586     * Signed 64-bit integer multiply.
4587     *
4588     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4589     *        WX
4590     *      x YZ
4591     *  --------
4592     *     ZW ZX
4593     *  YW YX
4594     *
4595     * The low word of the result holds ZX, the high word holds
4596     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4597     * it doesn't fit in the low 64 bits.
4598     *
4599     * Unlike most ARM math operations, multiply instructions have
4600     * restrictions on using the same register more than once (Rd and Rm
4601     * cannot be the same).
4602     */
4603    /* mul-long vAA, vBB, vCC */
4604    FETCH(r0, 1)                        @ r0<- CCBB
4605    and     r2, r0, #255                @ r2<- BB
4606    mov     r3, r0, lsr #8              @ r3<- CC
4607    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4608    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4609    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4610    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4611    mul     ip, r2, r1                  @  ip<- ZxW
4612    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4613    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4614    mov     r0, rINST, lsr #8           @ r0<- AA
4615    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4616    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4617    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4618    b       .LOP_MUL_LONG_finish
4619
4620/* ------------------------------ */
4621    .balign 64
4622.L_OP_DIV_LONG: /* 0x9e */
4623/* File: armv5te/OP_DIV_LONG.S */
4624/* File: armv5te/binopWide.S */
4625    /*
4626     * Generic 64-bit binary operation.  Provide an "instr" line that
4627     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4628     * This could be an ARM instruction or a function call.  (If the result
4629     * comes back in a register other than r0, you can override "result".)
4630     *
4631     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4632     * vCC (r1).  Useful for integer division and modulus.
4633     *
4634     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4635     *      xor-long, add-double, sub-double, mul-double, div-double,
4636     *      rem-double
4637     *
4638     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4639     */
4640    /* binop vAA, vBB, vCC */
4641    FETCH(r0, 1)                        @ r0<- CCBB
4642    mov     r9, rINST, lsr #8           @ r9<- AA
4643    and     r2, r0, #255                @ r2<- BB
4644    mov     r3, r0, lsr #8              @ r3<- CC
4645    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4646    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4647    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4648    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4649    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4650    .if 1
4651    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4652    beq     common_errDivideByZero
4653    .endif
4654    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4655
4656                               @ optional op; may set condition codes
4657    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4658    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4659    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4660    GOTO_OPCODE(ip)                     @ jump to next instruction
4661    /* 14-17 instructions */
4662
4663
4664/* ------------------------------ */
4665    .balign 64
4666.L_OP_REM_LONG: /* 0x9f */
4667/* File: armv5te/OP_REM_LONG.S */
4668/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4669/* File: armv5te/binopWide.S */
4670    /*
4671     * Generic 64-bit binary operation.  Provide an "instr" line that
4672     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4673     * This could be an ARM instruction or a function call.  (If the result
4674     * comes back in a register other than r0, you can override "result".)
4675     *
4676     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4677     * vCC (r1).  Useful for integer division and modulus.
4678     *
4679     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4680     *      xor-long, add-double, sub-double, mul-double, div-double,
4681     *      rem-double
4682     *
4683     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4684     */
4685    /* binop vAA, vBB, vCC */
4686    FETCH(r0, 1)                        @ r0<- CCBB
4687    mov     r9, rINST, lsr #8           @ r9<- AA
4688    and     r2, r0, #255                @ r2<- BB
4689    mov     r3, r0, lsr #8              @ r3<- CC
4690    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4691    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4692    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4693    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4694    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4695    .if 1
4696    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4697    beq     common_errDivideByZero
4698    .endif
4699    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4700
4701                               @ optional op; may set condition codes
4702    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4703    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4704    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4705    GOTO_OPCODE(ip)                     @ jump to next instruction
4706    /* 14-17 instructions */
4707
4708
4709/* ------------------------------ */
4710    .balign 64
4711.L_OP_AND_LONG: /* 0xa0 */
4712/* File: armv5te/OP_AND_LONG.S */
4713/* File: armv5te/binopWide.S */
4714    /*
4715     * Generic 64-bit binary operation.  Provide an "instr" line that
4716     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4717     * This could be an ARM instruction or a function call.  (If the result
4718     * comes back in a register other than r0, you can override "result".)
4719     *
4720     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4721     * vCC (r1).  Useful for integer division and modulus.
4722     *
4723     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4724     *      xor-long, add-double, sub-double, mul-double, div-double,
4725     *      rem-double
4726     *
4727     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4728     */
4729    /* binop vAA, vBB, vCC */
4730    FETCH(r0, 1)                        @ r0<- CCBB
4731    mov     r9, rINST, lsr #8           @ r9<- AA
4732    and     r2, r0, #255                @ r2<- BB
4733    mov     r3, r0, lsr #8              @ r3<- CC
4734    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4735    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4736    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4737    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4738    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4739    .if 0
4740    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4741    beq     common_errDivideByZero
4742    .endif
4743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4744
4745    and     r0, r0, r2                           @ optional op; may set condition codes
4746    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4747    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4748    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4749    GOTO_OPCODE(ip)                     @ jump to next instruction
4750    /* 14-17 instructions */
4751
4752
4753/* ------------------------------ */
4754    .balign 64
4755.L_OP_OR_LONG: /* 0xa1 */
4756/* File: armv5te/OP_OR_LONG.S */
4757/* File: armv5te/binopWide.S */
4758    /*
4759     * Generic 64-bit binary operation.  Provide an "instr" line that
4760     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4761     * This could be an ARM instruction or a function call.  (If the result
4762     * comes back in a register other than r0, you can override "result".)
4763     *
4764     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4765     * vCC (r1).  Useful for integer division and modulus.
4766     *
4767     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4768     *      xor-long, add-double, sub-double, mul-double, div-double,
4769     *      rem-double
4770     *
4771     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4772     */
4773    /* binop vAA, vBB, vCC */
4774    FETCH(r0, 1)                        @ r0<- CCBB
4775    mov     r9, rINST, lsr #8           @ r9<- AA
4776    and     r2, r0, #255                @ r2<- BB
4777    mov     r3, r0, lsr #8              @ r3<- CC
4778    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4779    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4780    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4781    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4782    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4783    .if 0
4784    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4785    beq     common_errDivideByZero
4786    .endif
4787    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4788
4789    orr     r0, r0, r2                           @ optional op; may set condition codes
4790    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4791    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4792    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4793    GOTO_OPCODE(ip)                     @ jump to next instruction
4794    /* 14-17 instructions */
4795
4796
4797/* ------------------------------ */
4798    .balign 64
4799.L_OP_XOR_LONG: /* 0xa2 */
4800/* File: armv5te/OP_XOR_LONG.S */
4801/* File: armv5te/binopWide.S */
4802    /*
4803     * Generic 64-bit binary operation.  Provide an "instr" line that
4804     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4805     * This could be an ARM instruction or a function call.  (If the result
4806     * comes back in a register other than r0, you can override "result".)
4807     *
4808     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4809     * vCC (r1).  Useful for integer division and modulus.
4810     *
4811     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4812     *      xor-long, add-double, sub-double, mul-double, div-double,
4813     *      rem-double
4814     *
4815     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4816     */
4817    /* binop vAA, vBB, vCC */
4818    FETCH(r0, 1)                        @ r0<- CCBB
4819    mov     r9, rINST, lsr #8           @ r9<- AA
4820    and     r2, r0, #255                @ r2<- BB
4821    mov     r3, r0, lsr #8              @ r3<- CC
4822    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4823    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4824    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4825    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4826    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4827    .if 0
4828    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4829    beq     common_errDivideByZero
4830    .endif
4831    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4832
4833    eor     r0, r0, r2                           @ optional op; may set condition codes
4834    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4835    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4836    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4837    GOTO_OPCODE(ip)                     @ jump to next instruction
4838    /* 14-17 instructions */
4839
4840
4841/* ------------------------------ */
4842    .balign 64
4843.L_OP_SHL_LONG: /* 0xa3 */
4844/* File: armv5te/OP_SHL_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    /* shl-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                 @ r2<- r2 & 0x3f
4860    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4861
4862    mov     r1, r1, asl r2              @  r1<- r1 << r2
4863    rsb     r3, r2, #32                 @  r3<- 32 - r2
4864    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4865    subs    ip, r2, #32                 @  ip<- r2 - 32
4866    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4867    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4868    b       .LOP_SHL_LONG_finish
4869
4870/* ------------------------------ */
4871    .balign 64
4872.L_OP_SHR_LONG: /* 0xa4 */
4873/* File: armv5te/OP_SHR_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    /* shr-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, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4897    b       .LOP_SHR_LONG_finish
4898
4899/* ------------------------------ */
4900    .balign 64
4901.L_OP_USHR_LONG: /* 0xa5 */
4902/* File: armv5te/OP_USHR_LONG.S */
4903    /*
4904     * Long integer shift.  This is different from the generic 32/64-bit
4905     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4906     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4907     * 6 bits of the shift distance.
4908     */
4909    /* ushr-long vAA, vBB, vCC */
4910    FETCH(r0, 1)                        @ r0<- CCBB
4911    mov     r9, rINST, lsr #8           @ r9<- AA
4912    and     r3, r0, #255                @ r3<- BB
4913    mov     r0, r0, lsr #8              @ r0<- CC
4914    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4915    GET_VREG(r2, r0)                    @ r2<- vCC
4916    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4917    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4918    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4919
4920    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4921    rsb     r3, r2, #32                 @  r3<- 32 - r2
4922    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4923    subs    ip, r2, #32                 @  ip<- r2 - 32
4924    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4925    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4926    b       .LOP_USHR_LONG_finish
4927
4928/* ------------------------------ */
4929    .balign 64
4930.L_OP_ADD_FLOAT: /* 0xa6 */
4931/* File: arm-vfp/OP_ADD_FLOAT.S */
4932/* File: arm-vfp/fbinop.S */
4933    /*
4934     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4935     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4936     * use the "softfp" ABI, this must be an instruction, not a function call.
4937     *
4938     * For: add-float, sub-float, mul-float, div-float
4939     */
4940    /* floatop vAA, vBB, vCC */
4941    FETCH(r0, 1)                        @ r0<- CCBB
4942    mov     r9, rINST, lsr #8           @ r9<- AA
4943    mov     r3, r0, lsr #8              @ r3<- CC
4944    and     r2, r0, #255                @ r2<- BB
4945    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4946    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4947    flds    s1, [r3]                    @ s1<- vCC
4948    flds    s0, [r2]                    @ s0<- vBB
4949
4950    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4951    fadds   s2, s0, s1                              @ s2<- op
4952    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4953    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4954    fsts    s2, [r9]                    @ vAA<- s2
4955    GOTO_OPCODE(ip)                     @ jump to next instruction
4956
4957
4958/* ------------------------------ */
4959    .balign 64
4960.L_OP_SUB_FLOAT: /* 0xa7 */
4961/* File: arm-vfp/OP_SUB_FLOAT.S */
4962/* File: arm-vfp/fbinop.S */
4963    /*
4964     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4965     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4966     * use the "softfp" ABI, this must be an instruction, not a function call.
4967     *
4968     * For: add-float, sub-float, mul-float, div-float
4969     */
4970    /* floatop vAA, vBB, vCC */
4971    FETCH(r0, 1)                        @ r0<- CCBB
4972    mov     r9, rINST, lsr #8           @ r9<- AA
4973    mov     r3, r0, lsr #8              @ r3<- CC
4974    and     r2, r0, #255                @ r2<- BB
4975    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4976    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4977    flds    s1, [r3]                    @ s1<- vCC
4978    flds    s0, [r2]                    @ s0<- vBB
4979
4980    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4981    fsubs   s2, s0, s1                              @ s2<- op
4982    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4983    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4984    fsts    s2, [r9]                    @ vAA<- s2
4985    GOTO_OPCODE(ip)                     @ jump to next instruction
4986
4987
4988/* ------------------------------ */
4989    .balign 64
4990.L_OP_MUL_FLOAT: /* 0xa8 */
4991/* File: arm-vfp/OP_MUL_FLOAT.S */
4992/* File: arm-vfp/fbinop.S */
4993    /*
4994     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4995     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4996     * use the "softfp" ABI, this must be an instruction, not a function call.
4997     *
4998     * For: add-float, sub-float, mul-float, div-float
4999     */
5000    /* floatop vAA, vBB, vCC */
5001    FETCH(r0, 1)                        @ r0<- CCBB
5002    mov     r9, rINST, lsr #8           @ r9<- AA
5003    mov     r3, r0, lsr #8              @ r3<- CC
5004    and     r2, r0, #255                @ r2<- BB
5005    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5006    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5007    flds    s1, [r3]                    @ s1<- vCC
5008    flds    s0, [r2]                    @ s0<- vBB
5009
5010    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5011    fmuls   s2, s0, s1                              @ s2<- op
5012    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5013    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5014    fsts    s2, [r9]                    @ vAA<- s2
5015    GOTO_OPCODE(ip)                     @ jump to next instruction
5016
5017
5018/* ------------------------------ */
5019    .balign 64
5020.L_OP_DIV_FLOAT: /* 0xa9 */
5021/* File: arm-vfp/OP_DIV_FLOAT.S */
5022/* File: arm-vfp/fbinop.S */
5023    /*
5024     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5025     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5026     * use the "softfp" ABI, this must be an instruction, not a function call.
5027     *
5028     * For: add-float, sub-float, mul-float, div-float
5029     */
5030    /* floatop vAA, vBB, vCC */
5031    FETCH(r0, 1)                        @ r0<- CCBB
5032    mov     r9, rINST, lsr #8           @ r9<- AA
5033    mov     r3, r0, lsr #8              @ r3<- CC
5034    and     r2, r0, #255                @ r2<- BB
5035    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5036    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5037    flds    s1, [r3]                    @ s1<- vCC
5038    flds    s0, [r2]                    @ s0<- vBB
5039
5040    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5041    fdivs   s2, s0, s1                              @ s2<- op
5042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5043    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5044    fsts    s2, [r9]                    @ vAA<- s2
5045    GOTO_OPCODE(ip)                     @ jump to next instruction
5046
5047
5048/* ------------------------------ */
5049    .balign 64
5050.L_OP_REM_FLOAT: /* 0xaa */
5051/* File: armv5te/OP_REM_FLOAT.S */
5052/* EABI doesn't define a float remainder function, but libm does */
5053/* File: armv5te/binop.S */
5054    /*
5055     * Generic 32-bit binary operation.  Provide an "instr" line that
5056     * specifies an instruction that performs "result = r0 op r1".
5057     * This could be an ARM instruction or a function call.  (If the result
5058     * comes back in a register other than r0, you can override "result".)
5059     *
5060     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5061     * vCC (r1).  Useful for integer division and modulus.  Note that we
5062     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5063     * handles it correctly.
5064     *
5065     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5066     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5067     *      mul-float, div-float, rem-float
5068     */
5069    /* binop vAA, vBB, vCC */
5070    FETCH(r0, 1)                        @ r0<- CCBB
5071    mov     r9, rINST, lsr #8           @ r9<- AA
5072    mov     r3, r0, lsr #8              @ r3<- CC
5073    and     r2, r0, #255                @ r2<- BB
5074    GET_VREG(r1, r3)                    @ r1<- vCC
5075    GET_VREG(r0, r2)                    @ r0<- vBB
5076    .if 0
5077    cmp     r1, #0                      @ is second operand zero?
5078    beq     common_errDivideByZero
5079    .endif
5080
5081    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5082                               @ optional op; may set condition codes
5083    bl      fmodf                              @ r0<- op, r0-r3 changed
5084    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5085    SET_VREG(r0, r9)               @ vAA<- r0
5086    GOTO_OPCODE(ip)                     @ jump to next instruction
5087    /* 11-14 instructions */
5088
5089
5090/* ------------------------------ */
5091    .balign 64
5092.L_OP_ADD_DOUBLE: /* 0xab */
5093/* File: arm-vfp/OP_ADD_DOUBLE.S */
5094/* File: arm-vfp/fbinopWide.S */
5095    /*
5096     * Generic 64-bit double-precision floating point binary operation.
5097     * Provide an "instr" line that specifies an instruction that performs
5098     * "d2 = d0 op d1".
5099     *
5100     * for: add-double, sub-double, mul-double, div-double
5101     */
5102    /* doubleop vAA, vBB, vCC */
5103    FETCH(r0, 1)                        @ r0<- CCBB
5104    mov     r9, rINST, lsr #8           @ r9<- AA
5105    mov     r3, r0, lsr #8              @ r3<- CC
5106    and     r2, r0, #255                @ r2<- BB
5107    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5108    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5109    fldd    d1, [r3]                    @ d1<- vCC
5110    fldd    d0, [r2]                    @ d0<- vBB
5111
5112    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5113    faddd   d2, d0, d1                              @ s2<- op
5114    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5115    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5116    fstd    d2, [r9]                    @ vAA<- d2
5117    GOTO_OPCODE(ip)                     @ jump to next instruction
5118
5119
5120/* ------------------------------ */
5121    .balign 64
5122.L_OP_SUB_DOUBLE: /* 0xac */
5123/* File: arm-vfp/OP_SUB_DOUBLE.S */
5124/* File: arm-vfp/fbinopWide.S */
5125    /*
5126     * Generic 64-bit double-precision floating point binary operation.
5127     * Provide an "instr" line that specifies an instruction that performs
5128     * "d2 = d0 op d1".
5129     *
5130     * for: add-double, sub-double, mul-double, div-double
5131     */
5132    /* doubleop vAA, vBB, vCC */
5133    FETCH(r0, 1)                        @ r0<- CCBB
5134    mov     r9, rINST, lsr #8           @ r9<- AA
5135    mov     r3, r0, lsr #8              @ r3<- CC
5136    and     r2, r0, #255                @ r2<- BB
5137    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5138    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5139    fldd    d1, [r3]                    @ d1<- vCC
5140    fldd    d0, [r2]                    @ d0<- vBB
5141
5142    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5143    fsubd   d2, d0, d1                              @ s2<- op
5144    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5145    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5146    fstd    d2, [r9]                    @ vAA<- d2
5147    GOTO_OPCODE(ip)                     @ jump to next instruction
5148
5149
5150/* ------------------------------ */
5151    .balign 64
5152.L_OP_MUL_DOUBLE: /* 0xad */
5153/* File: arm-vfp/OP_MUL_DOUBLE.S */
5154/* File: arm-vfp/fbinopWide.S */
5155    /*
5156     * Generic 64-bit double-precision floating point binary operation.
5157     * Provide an "instr" line that specifies an instruction that performs
5158     * "d2 = d0 op d1".
5159     *
5160     * for: add-double, sub-double, mul-double, div-double
5161     */
5162    /* doubleop vAA, vBB, vCC */
5163    FETCH(r0, 1)                        @ r0<- CCBB
5164    mov     r9, rINST, lsr #8           @ r9<- AA
5165    mov     r3, r0, lsr #8              @ r3<- CC
5166    and     r2, r0, #255                @ r2<- BB
5167    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5168    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5169    fldd    d1, [r3]                    @ d1<- vCC
5170    fldd    d0, [r2]                    @ d0<- vBB
5171
5172    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5173    fmuld   d2, d0, d1                              @ s2<- op
5174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5175    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5176    fstd    d2, [r9]                    @ vAA<- d2
5177    GOTO_OPCODE(ip)                     @ jump to next instruction
5178
5179
5180/* ------------------------------ */
5181    .balign 64
5182.L_OP_DIV_DOUBLE: /* 0xae */
5183/* File: arm-vfp/OP_DIV_DOUBLE.S */
5184/* File: arm-vfp/fbinopWide.S */
5185    /*
5186     * Generic 64-bit double-precision floating point binary operation.
5187     * Provide an "instr" line that specifies an instruction that performs
5188     * "d2 = d0 op d1".
5189     *
5190     * for: add-double, sub-double, mul-double, div-double
5191     */
5192    /* doubleop vAA, vBB, vCC */
5193    FETCH(r0, 1)                        @ r0<- CCBB
5194    mov     r9, rINST, lsr #8           @ r9<- AA
5195    mov     r3, r0, lsr #8              @ r3<- CC
5196    and     r2, r0, #255                @ r2<- BB
5197    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5198    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5199    fldd    d1, [r3]                    @ d1<- vCC
5200    fldd    d0, [r2]                    @ d0<- vBB
5201
5202    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5203    fdivd   d2, d0, d1                              @ s2<- op
5204    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5205    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5206    fstd    d2, [r9]                    @ vAA<- d2
5207    GOTO_OPCODE(ip)                     @ jump to next instruction
5208
5209
5210/* ------------------------------ */
5211    .balign 64
5212.L_OP_REM_DOUBLE: /* 0xaf */
5213/* File: armv5te/OP_REM_DOUBLE.S */
5214/* EABI doesn't define a double remainder function, but libm does */
5215/* File: armv5te/binopWide.S */
5216    /*
5217     * Generic 64-bit binary operation.  Provide an "instr" line that
5218     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5219     * This could be an ARM instruction or a function call.  (If the result
5220     * comes back in a register other than r0, you can override "result".)
5221     *
5222     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5223     * vCC (r1).  Useful for integer division and modulus.
5224     *
5225     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5226     *      xor-long, add-double, sub-double, mul-double, div-double,
5227     *      rem-double
5228     *
5229     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5230     */
5231    /* binop vAA, vBB, vCC */
5232    FETCH(r0, 1)                        @ r0<- CCBB
5233    mov     r9, rINST, lsr #8           @ r9<- AA
5234    and     r2, r0, #255                @ r2<- BB
5235    mov     r3, r0, lsr #8              @ r3<- CC
5236    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5237    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5238    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5239    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5240    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5241    .if 0
5242    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5243    beq     common_errDivideByZero
5244    .endif
5245    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5246
5247                               @ optional op; may set condition codes
5248    bl      fmod                              @ result<- op, r0-r3 changed
5249    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5250    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5251    GOTO_OPCODE(ip)                     @ jump to next instruction
5252    /* 14-17 instructions */
5253
5254
5255/* ------------------------------ */
5256    .balign 64
5257.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5258/* File: armv5te/OP_ADD_INT_2ADDR.S */
5259/* File: armv5te/binop2addr.S */
5260    /*
5261     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5262     * that specifies an instruction that performs "result = r0 op r1".
5263     * This could be an ARM instruction or a function call.  (If the result
5264     * comes back in a register other than r0, you can override "result".)
5265     *
5266     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5267     * vCC (r1).  Useful for integer division and modulus.
5268     *
5269     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5270     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5271     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5272     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5273     */
5274    /* binop/2addr vA, vB */
5275    mov     r9, rINST, lsr #8           @ r9<- A+
5276    mov     r3, rINST, lsr #12          @ r3<- B
5277    and     r9, r9, #15
5278    GET_VREG(r1, r3)                    @ r1<- vB
5279    GET_VREG(r0, r9)                    @ r0<- vA
5280    .if 0
5281    cmp     r1, #0                      @ is second operand zero?
5282    beq     common_errDivideByZero
5283    .endif
5284    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5285
5286                               @ optional op; may set condition codes
5287    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5288    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5289    SET_VREG(r0, r9)               @ vAA<- r0
5290    GOTO_OPCODE(ip)                     @ jump to next instruction
5291    /* 10-13 instructions */
5292
5293
5294/* ------------------------------ */
5295    .balign 64
5296.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5297/* File: armv5te/OP_SUB_INT_2ADDR.S */
5298/* File: armv5te/binop2addr.S */
5299    /*
5300     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5301     * that specifies an instruction that performs "result = r0 op r1".
5302     * This could be an ARM instruction or a function call.  (If the result
5303     * comes back in a register other than r0, you can override "result".)
5304     *
5305     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5306     * vCC (r1).  Useful for integer division and modulus.
5307     *
5308     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5309     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5310     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5311     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5312     */
5313    /* binop/2addr vA, vB */
5314    mov     r9, rINST, lsr #8           @ r9<- A+
5315    mov     r3, rINST, lsr #12          @ r3<- B
5316    and     r9, r9, #15
5317    GET_VREG(r1, r3)                    @ r1<- vB
5318    GET_VREG(r0, r9)                    @ r0<- vA
5319    .if 0
5320    cmp     r1, #0                      @ is second operand zero?
5321    beq     common_errDivideByZero
5322    .endif
5323    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5324
5325                               @ optional op; may set condition codes
5326    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5327    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5328    SET_VREG(r0, r9)               @ vAA<- r0
5329    GOTO_OPCODE(ip)                     @ jump to next instruction
5330    /* 10-13 instructions */
5331
5332
5333/* ------------------------------ */
5334    .balign 64
5335.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5336/* File: armv5te/OP_MUL_INT_2ADDR.S */
5337/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5338/* File: armv5te/binop2addr.S */
5339    /*
5340     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5341     * that specifies an instruction that performs "result = r0 op r1".
5342     * This could be an ARM instruction or a function call.  (If the result
5343     * comes back in a register other than r0, you can override "result".)
5344     *
5345     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5346     * vCC (r1).  Useful for integer division and modulus.
5347     *
5348     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5349     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5350     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5351     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5352     */
5353    /* binop/2addr vA, vB */
5354    mov     r9, rINST, lsr #8           @ r9<- A+
5355    mov     r3, rINST, lsr #12          @ r3<- B
5356    and     r9, r9, #15
5357    GET_VREG(r1, r3)                    @ r1<- vB
5358    GET_VREG(r0, r9)                    @ r0<- vA
5359    .if 0
5360    cmp     r1, #0                      @ is second operand zero?
5361    beq     common_errDivideByZero
5362    .endif
5363    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5364
5365                               @ optional op; may set condition codes
5366    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5367    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5368    SET_VREG(r0, r9)               @ vAA<- r0
5369    GOTO_OPCODE(ip)                     @ jump to next instruction
5370    /* 10-13 instructions */
5371
5372
5373/* ------------------------------ */
5374    .balign 64
5375.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5376/* File: armv5te/OP_DIV_INT_2ADDR.S */
5377/* File: armv5te/binop2addr.S */
5378    /*
5379     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5380     * that specifies an instruction that performs "result = r0 op r1".
5381     * This could be an ARM instruction or a function call.  (If the result
5382     * comes back in a register other than r0, you can override "result".)
5383     *
5384     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5385     * vCC (r1).  Useful for integer division and modulus.
5386     *
5387     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5388     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5389     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5390     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5391     */
5392    /* binop/2addr vA, vB */
5393    mov     r9, rINST, lsr #8           @ r9<- A+
5394    mov     r3, rINST, lsr #12          @ r3<- B
5395    and     r9, r9, #15
5396    GET_VREG(r1, r3)                    @ r1<- vB
5397    GET_VREG(r0, r9)                    @ r0<- vA
5398    .if 1
5399    cmp     r1, #0                      @ is second operand zero?
5400    beq     common_errDivideByZero
5401    .endif
5402    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5403
5404                               @ optional op; may set condition codes
5405    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5406    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5407    SET_VREG(r0, r9)               @ vAA<- r0
5408    GOTO_OPCODE(ip)                     @ jump to next instruction
5409    /* 10-13 instructions */
5410
5411
5412/* ------------------------------ */
5413    .balign 64
5414.L_OP_REM_INT_2ADDR: /* 0xb4 */
5415/* File: armv5te/OP_REM_INT_2ADDR.S */
5416/* idivmod returns quotient in r0 and remainder in r1 */
5417/* File: armv5te/binop2addr.S */
5418    /*
5419     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5420     * that specifies an instruction that performs "result = r0 op r1".
5421     * This could be an ARM instruction or a function call.  (If the result
5422     * comes back in a register other than r0, you can override "result".)
5423     *
5424     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5425     * vCC (r1).  Useful for integer division and modulus.
5426     *
5427     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5428     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5429     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5430     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5431     */
5432    /* binop/2addr vA, vB */
5433    mov     r9, rINST, lsr #8           @ r9<- A+
5434    mov     r3, rINST, lsr #12          @ r3<- B
5435    and     r9, r9, #15
5436    GET_VREG(r1, r3)                    @ r1<- vB
5437    GET_VREG(r0, r9)                    @ r0<- vA
5438    .if 1
5439    cmp     r1, #0                      @ is second operand zero?
5440    beq     common_errDivideByZero
5441    .endif
5442    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5443
5444                               @ optional op; may set condition codes
5445    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5446    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5447    SET_VREG(r1, r9)               @ vAA<- r1
5448    GOTO_OPCODE(ip)                     @ jump to next instruction
5449    /* 10-13 instructions */
5450
5451
5452/* ------------------------------ */
5453    .balign 64
5454.L_OP_AND_INT_2ADDR: /* 0xb5 */
5455/* File: armv5te/OP_AND_INT_2ADDR.S */
5456/* File: armv5te/binop2addr.S */
5457    /*
5458     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5459     * that specifies an instruction that performs "result = r0 op r1".
5460     * This could be an ARM instruction or a function call.  (If the result
5461     * comes back in a register other than r0, you can override "result".)
5462     *
5463     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5464     * vCC (r1).  Useful for integer division and modulus.
5465     *
5466     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5467     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5468     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5469     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5470     */
5471    /* binop/2addr vA, vB */
5472    mov     r9, rINST, lsr #8           @ r9<- A+
5473    mov     r3, rINST, lsr #12          @ r3<- B
5474    and     r9, r9, #15
5475    GET_VREG(r1, r3)                    @ r1<- vB
5476    GET_VREG(r0, r9)                    @ r0<- vA
5477    .if 0
5478    cmp     r1, #0                      @ is second operand zero?
5479    beq     common_errDivideByZero
5480    .endif
5481    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5482
5483                               @ optional op; may set condition codes
5484    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5486    SET_VREG(r0, r9)               @ vAA<- r0
5487    GOTO_OPCODE(ip)                     @ jump to next instruction
5488    /* 10-13 instructions */
5489
5490
5491/* ------------------------------ */
5492    .balign 64
5493.L_OP_OR_INT_2ADDR: /* 0xb6 */
5494/* File: armv5te/OP_OR_INT_2ADDR.S */
5495/* File: armv5te/binop2addr.S */
5496    /*
5497     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5498     * that specifies an instruction that performs "result = r0 op r1".
5499     * This could be an ARM instruction or a function call.  (If the result
5500     * comes back in a register other than r0, you can override "result".)
5501     *
5502     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5503     * vCC (r1).  Useful for integer division and modulus.
5504     *
5505     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5506     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5507     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5508     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5509     */
5510    /* binop/2addr vA, vB */
5511    mov     r9, rINST, lsr #8           @ r9<- A+
5512    mov     r3, rINST, lsr #12          @ r3<- B
5513    and     r9, r9, #15
5514    GET_VREG(r1, r3)                    @ r1<- vB
5515    GET_VREG(r0, r9)                    @ r0<- vA
5516    .if 0
5517    cmp     r1, #0                      @ is second operand zero?
5518    beq     common_errDivideByZero
5519    .endif
5520    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5521
5522                               @ optional op; may set condition codes
5523    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5524    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5525    SET_VREG(r0, r9)               @ vAA<- r0
5526    GOTO_OPCODE(ip)                     @ jump to next instruction
5527    /* 10-13 instructions */
5528
5529
5530/* ------------------------------ */
5531    .balign 64
5532.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5533/* File: armv5te/OP_XOR_INT_2ADDR.S */
5534/* File: armv5te/binop2addr.S */
5535    /*
5536     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5537     * that specifies an instruction that performs "result = r0 op r1".
5538     * This could be an ARM instruction or a function call.  (If the result
5539     * comes back in a register other than r0, you can override "result".)
5540     *
5541     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5542     * vCC (r1).  Useful for integer division and modulus.
5543     *
5544     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5545     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5546     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5547     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5548     */
5549    /* binop/2addr vA, vB */
5550    mov     r9, rINST, lsr #8           @ r9<- A+
5551    mov     r3, rINST, lsr #12          @ r3<- B
5552    and     r9, r9, #15
5553    GET_VREG(r1, r3)                    @ r1<- vB
5554    GET_VREG(r0, r9)                    @ r0<- vA
5555    .if 0
5556    cmp     r1, #0                      @ is second operand zero?
5557    beq     common_errDivideByZero
5558    .endif
5559    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5560
5561                               @ optional op; may set condition codes
5562    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5564    SET_VREG(r0, r9)               @ vAA<- r0
5565    GOTO_OPCODE(ip)                     @ jump to next instruction
5566    /* 10-13 instructions */
5567
5568
5569/* ------------------------------ */
5570    .balign 64
5571.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5572/* File: armv5te/OP_SHL_INT_2ADDR.S */
5573/* File: armv5te/binop2addr.S */
5574    /*
5575     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5576     * that specifies an instruction that performs "result = r0 op r1".
5577     * This could be an ARM instruction or a function call.  (If the result
5578     * comes back in a register other than r0, you can override "result".)
5579     *
5580     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5581     * vCC (r1).  Useful for integer division and modulus.
5582     *
5583     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5584     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5585     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5586     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5587     */
5588    /* binop/2addr vA, vB */
5589    mov     r9, rINST, lsr #8           @ r9<- A+
5590    mov     r3, rINST, lsr #12          @ r3<- B
5591    and     r9, r9, #15
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, asl 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_SHR_INT_2ADDR: /* 0xb9 */
5611/* File: armv5te/OP_SHR_INT_2ADDR.S */
5612/* File: armv5te/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     r9, rINST, lsr #8           @ r9<- A+
5629    mov     r3, rINST, lsr #12          @ r3<- B
5630    and     r9, r9, #15
5631    GET_VREG(r1, r3)                    @ r1<- vB
5632    GET_VREG(r0, r9)                    @ r0<- vA
5633    .if 0
5634    cmp     r1, #0                      @ is second operand zero?
5635    beq     common_errDivideByZero
5636    .endif
5637    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5638
5639    and     r1, r1, #31                           @ optional op; may set condition codes
5640    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5642    SET_VREG(r0, r9)               @ vAA<- r0
5643    GOTO_OPCODE(ip)                     @ jump to next instruction
5644    /* 10-13 instructions */
5645
5646
5647/* ------------------------------ */
5648    .balign 64
5649.L_OP_USHR_INT_2ADDR: /* 0xba */
5650/* File: armv5te/OP_USHR_INT_2ADDR.S */
5651/* File: armv5te/binop2addr.S */
5652    /*
5653     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5654     * that specifies an instruction that performs "result = r0 op r1".
5655     * This could be an ARM instruction or a function call.  (If the result
5656     * comes back in a register other than r0, you can override "result".)
5657     *
5658     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5659     * vCC (r1).  Useful for integer division and modulus.
5660     *
5661     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5662     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5663     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5664     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5665     */
5666    /* binop/2addr vA, vB */
5667    mov     r9, rINST, lsr #8           @ r9<- A+
5668    mov     r3, rINST, lsr #12          @ r3<- B
5669    and     r9, r9, #15
5670    GET_VREG(r1, r3)                    @ r1<- vB
5671    GET_VREG(r0, r9)                    @ r0<- vA
5672    .if 0
5673    cmp     r1, #0                      @ is second operand zero?
5674    beq     common_errDivideByZero
5675    .endif
5676    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5677
5678    and     r1, r1, #31                           @ optional op; may set condition codes
5679    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5680    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5681    SET_VREG(r0, r9)               @ vAA<- r0
5682    GOTO_OPCODE(ip)                     @ jump to next instruction
5683    /* 10-13 instructions */
5684
5685
5686/* ------------------------------ */
5687    .balign 64
5688.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5689/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5690/* File: armv5te/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     r9, rINST, lsr #8           @ r9<- A+
5707    mov     r1, rINST, lsr #12          @ r1<- B
5708    and     r9, r9, #15
5709    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5710    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5711    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5712    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5713    .if 0
5714    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5715    beq     common_errDivideByZero
5716    .endif
5717    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5718
5719    adds    r0, r0, r2                           @ optional op; may set condition codes
5720    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5722    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5723    GOTO_OPCODE(ip)                     @ jump to next instruction
5724    /* 12-15 instructions */
5725
5726
5727/* ------------------------------ */
5728    .balign 64
5729.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5730/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5731/* File: armv5te/binopWide2addr.S */
5732    /*
5733     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5734     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5735     * This could be an ARM instruction or a function call.  (If the result
5736     * comes back in a register other than r0, you can override "result".)
5737     *
5738     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5739     * vCC (r1).  Useful for integer division and modulus.
5740     *
5741     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5742     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5743     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5744     *      rem-double/2addr
5745     */
5746    /* binop/2addr vA, vB */
5747    mov     r9, rINST, lsr #8           @ r9<- A+
5748    mov     r1, rINST, lsr #12          @ r1<- B
5749    and     r9, r9, #15
5750    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5751    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5752    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5753    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5754    .if 0
5755    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5756    beq     common_errDivideByZero
5757    .endif
5758    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5759
5760    subs    r0, r0, r2                           @ optional op; may set condition codes
5761    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5763    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5764    GOTO_OPCODE(ip)                     @ jump to next instruction
5765    /* 12-15 instructions */
5766
5767
5768/* ------------------------------ */
5769    .balign 64
5770.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5771/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5772    /*
5773     * Signed 64-bit integer multiply, "/2addr" version.
5774     *
5775     * See OP_MUL_LONG for an explanation.
5776     *
5777     * We get a little tight on registers, so to avoid looking up &fp[A]
5778     * again we stuff it into rINST.
5779     */
5780    /* mul-long/2addr vA, vB */
5781    mov     r9, rINST, lsr #8           @ r9<- A+
5782    mov     r1, rINST, lsr #12          @ r1<- B
5783    and     r9, r9, #15
5784    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5785    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5786    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5787    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5788    mul     ip, r2, r1                  @  ip<- ZxW
5789    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5790    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5791    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5792    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5793    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5795    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5796    GOTO_OPCODE(ip)                     @ jump to next instruction
5797
5798/* ------------------------------ */
5799    .balign 64
5800.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5801/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5802/* File: armv5te/binopWide2addr.S */
5803    /*
5804     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5805     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5806     * This could be an ARM instruction or a function call.  (If the result
5807     * comes back in a register other than r0, you can override "result".)
5808     *
5809     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5810     * vCC (r1).  Useful for integer division and modulus.
5811     *
5812     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5813     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5814     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5815     *      rem-double/2addr
5816     */
5817    /* binop/2addr vA, vB */
5818    mov     r9, rINST, lsr #8           @ r9<- A+
5819    mov     r1, rINST, lsr #12          @ r1<- B
5820    and     r9, r9, #15
5821    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5822    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5823    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5824    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5825    .if 1
5826    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5827    beq     common_errDivideByZero
5828    .endif
5829    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5830
5831                               @ optional op; may set condition codes
5832    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5833    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5834    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5835    GOTO_OPCODE(ip)                     @ jump to next instruction
5836    /* 12-15 instructions */
5837
5838
5839/* ------------------------------ */
5840    .balign 64
5841.L_OP_REM_LONG_2ADDR: /* 0xbf */
5842/* File: armv5te/OP_REM_LONG_2ADDR.S */
5843/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5844/* File: armv5te/binopWide2addr.S */
5845    /*
5846     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5847     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5848     * This could be an ARM instruction or a function call.  (If the result
5849     * comes back in a register other than r0, you can override "result".)
5850     *
5851     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5852     * vCC (r1).  Useful for integer division and modulus.
5853     *
5854     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5855     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5856     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5857     *      rem-double/2addr
5858     */
5859    /* binop/2addr vA, vB */
5860    mov     r9, rINST, lsr #8           @ r9<- A+
5861    mov     r1, rINST, lsr #12          @ r1<- B
5862    and     r9, r9, #15
5863    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5864    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5865    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5866    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5867    .if 1
5868    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5869    beq     common_errDivideByZero
5870    .endif
5871    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5872
5873                               @ optional op; may set condition codes
5874    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5875    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5876    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5877    GOTO_OPCODE(ip)                     @ jump to next instruction
5878    /* 12-15 instructions */
5879
5880
5881/* ------------------------------ */
5882    .balign 64
5883.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5884/* File: armv5te/OP_AND_LONG_2ADDR.S */
5885/* File: armv5te/binopWide2addr.S */
5886    /*
5887     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5888     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5889     * This could be an ARM instruction or a function call.  (If the result
5890     * comes back in a register other than r0, you can override "result".)
5891     *
5892     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5893     * vCC (r1).  Useful for integer division and modulus.
5894     *
5895     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5896     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5897     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5898     *      rem-double/2addr
5899     */
5900    /* binop/2addr vA, vB */
5901    mov     r9, rINST, lsr #8           @ r9<- A+
5902    mov     r1, rINST, lsr #12          @ r1<- B
5903    and     r9, r9, #15
5904    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5905    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5906    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5907    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5908    .if 0
5909    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5910    beq     common_errDivideByZero
5911    .endif
5912    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5913
5914    and     r0, r0, r2                           @ optional op; may set condition codes
5915    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5916    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5917    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5918    GOTO_OPCODE(ip)                     @ jump to next instruction
5919    /* 12-15 instructions */
5920
5921
5922/* ------------------------------ */
5923    .balign 64
5924.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5925/* File: armv5te/OP_OR_LONG_2ADDR.S */
5926/* File: armv5te/binopWide2addr.S */
5927    /*
5928     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5929     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5930     * This could be an ARM instruction or a function call.  (If the result
5931     * comes back in a register other than r0, you can override "result".)
5932     *
5933     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5934     * vCC (r1).  Useful for integer division and modulus.
5935     *
5936     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5937     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5938     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5939     *      rem-double/2addr
5940     */
5941    /* binop/2addr vA, vB */
5942    mov     r9, rINST, lsr #8           @ r9<- A+
5943    mov     r1, rINST, lsr #12          @ r1<- B
5944    and     r9, r9, #15
5945    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5946    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5947    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5948    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5949    .if 0
5950    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5951    beq     common_errDivideByZero
5952    .endif
5953    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5954
5955    orr     r0, r0, r2                           @ optional op; may set condition codes
5956    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5958    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5959    GOTO_OPCODE(ip)                     @ jump to next instruction
5960    /* 12-15 instructions */
5961
5962
5963/* ------------------------------ */
5964    .balign 64
5965.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5966/* File: armv5te/OP_XOR_LONG_2ADDR.S */
5967/* File: armv5te/binopWide2addr.S */
5968    /*
5969     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5970     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5971     * This could be an ARM instruction or a function call.  (If the result
5972     * comes back in a register other than r0, you can override "result".)
5973     *
5974     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5975     * vCC (r1).  Useful for integer division and modulus.
5976     *
5977     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5978     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5979     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5980     *      rem-double/2addr
5981     */
5982    /* binop/2addr vA, vB */
5983    mov     r9, rINST, lsr #8           @ r9<- A+
5984    mov     r1, rINST, lsr #12          @ r1<- B
5985    and     r9, r9, #15
5986    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5987    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5988    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5989    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5990    .if 0
5991    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5992    beq     common_errDivideByZero
5993    .endif
5994    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5995
5996    eor     r0, r0, r2                           @ optional op; may set condition codes
5997    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
5998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5999    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6000    GOTO_OPCODE(ip)                     @ jump to next instruction
6001    /* 12-15 instructions */
6002
6003
6004/* ------------------------------ */
6005    .balign 64
6006.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6007/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6008    /*
6009     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6010     * 32-bit shift distance.
6011     */
6012    /* shl-long/2addr vA, vB */
6013    mov     r9, rINST, lsr #8           @ r9<- A+
6014    mov     r3, rINST, lsr #12          @ r3<- B
6015    and     r9, r9, #15
6016    GET_VREG(r2, r3)                    @ r2<- vB
6017    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6018    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6019    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6020
6021    mov     r1, r1, asl r2              @  r1<- r1 << r2
6022    rsb     r3, r2, #32                 @  r3<- 32 - r2
6023    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6024    subs    ip, r2, #32                 @  ip<- r2 - 32
6025    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6026    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6027    mov     r0, r0, asl r2              @  r0<- r0 << r2
6028    b       .LOP_SHL_LONG_2ADDR_finish
6029
6030/* ------------------------------ */
6031    .balign 64
6032.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6033/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6034    /*
6035     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6036     * 32-bit shift distance.
6037     */
6038    /* shr-long/2addr vA, vB */
6039    mov     r9, rINST, lsr #8           @ r9<- A+
6040    mov     r3, rINST, lsr #12          @ r3<- B
6041    and     r9, r9, #15
6042    GET_VREG(r2, r3)                    @ r2<- vB
6043    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6044    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6045    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6046
6047    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6048    rsb     r3, r2, #32                 @  r3<- 32 - r2
6049    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6050    subs    ip, r2, #32                 @  ip<- r2 - 32
6051    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6052    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6053    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6054    b       .LOP_SHR_LONG_2ADDR_finish
6055
6056/* ------------------------------ */
6057    .balign 64
6058.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6059/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6060    /*
6061     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6062     * 32-bit shift distance.
6063     */
6064    /* ushr-long/2addr vA, vB */
6065    mov     r9, rINST, lsr #8           @ r9<- A+
6066    mov     r3, rINST, lsr #12          @ r3<- B
6067    and     r9, r9, #15
6068    GET_VREG(r2, r3)                    @ r2<- vB
6069    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6070    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6071    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6072
6073    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6074    rsb     r3, r2, #32                 @  r3<- 32 - r2
6075    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6076    subs    ip, r2, #32                 @  ip<- r2 - 32
6077    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6078    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6079    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6080    b       .LOP_USHR_LONG_2ADDR_finish
6081
6082/* ------------------------------ */
6083    .balign 64
6084.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6085/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6086/* File: arm-vfp/fbinop2addr.S */
6087    /*
6088     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6089     * an "instr" line that specifies an instruction that performs
6090     * "s2 = s0 op s1".
6091     *
6092     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6093     */
6094    /* binop/2addr vA, vB */
6095    mov     r3, rINST, lsr #12          @ r3<- B
6096    mov     r9, rINST, lsr #8           @ r9<- A+
6097    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6098    and     r9, r9, #15                 @ r9<- A
6099    flds    s1, [r3]                    @ s1<- vB
6100    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6101    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6102    flds    s0, [r9]                    @ s0<- vA
6103
6104    fadds   s2, s0, s1                              @ s2<- op
6105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6106    fsts    s2, [r9]                    @ vAA<- s2
6107    GOTO_OPCODE(ip)                     @ jump to next instruction
6108
6109
6110/* ------------------------------ */
6111    .balign 64
6112.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6113/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6114/* File: arm-vfp/fbinop2addr.S */
6115    /*
6116     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6117     * an "instr" line that specifies an instruction that performs
6118     * "s2 = s0 op s1".
6119     *
6120     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6121     */
6122    /* binop/2addr vA, vB */
6123    mov     r3, rINST, lsr #12          @ r3<- B
6124    mov     r9, rINST, lsr #8           @ r9<- A+
6125    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6126    and     r9, r9, #15                 @ r9<- A
6127    flds    s1, [r3]                    @ s1<- vB
6128    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6129    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6130    flds    s0, [r9]                    @ s0<- vA
6131
6132    fsubs   s2, s0, s1                              @ s2<- op
6133    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6134    fsts    s2, [r9]                    @ vAA<- s2
6135    GOTO_OPCODE(ip)                     @ jump to next instruction
6136
6137
6138/* ------------------------------ */
6139    .balign 64
6140.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6141/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6142/* File: arm-vfp/fbinop2addr.S */
6143    /*
6144     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6145     * an "instr" line that specifies an instruction that performs
6146     * "s2 = s0 op s1".
6147     *
6148     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6149     */
6150    /* binop/2addr vA, vB */
6151    mov     r3, rINST, lsr #12          @ r3<- B
6152    mov     r9, rINST, lsr #8           @ r9<- A+
6153    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6154    and     r9, r9, #15                 @ r9<- A
6155    flds    s1, [r3]                    @ s1<- vB
6156    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6157    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6158    flds    s0, [r9]                    @ s0<- vA
6159
6160    fmuls   s2, s0, s1                              @ s2<- op
6161    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6162    fsts    s2, [r9]                    @ vAA<- s2
6163    GOTO_OPCODE(ip)                     @ jump to next instruction
6164
6165
6166/* ------------------------------ */
6167    .balign 64
6168.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6169/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6170/* File: arm-vfp/fbinop2addr.S */
6171    /*
6172     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6173     * an "instr" line that specifies an instruction that performs
6174     * "s2 = s0 op s1".
6175     *
6176     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6177     */
6178    /* binop/2addr vA, vB */
6179    mov     r3, rINST, lsr #12          @ r3<- B
6180    mov     r9, rINST, lsr #8           @ r9<- A+
6181    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6182    and     r9, r9, #15                 @ r9<- A
6183    flds    s1, [r3]                    @ s1<- vB
6184    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6185    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6186    flds    s0, [r9]                    @ s0<- vA
6187
6188    fdivs   s2, s0, s1                              @ s2<- op
6189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6190    fsts    s2, [r9]                    @ vAA<- s2
6191    GOTO_OPCODE(ip)                     @ jump to next instruction
6192
6193
6194/* ------------------------------ */
6195    .balign 64
6196.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6197/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6198/* EABI doesn't define a float remainder function, but libm does */
6199/* File: armv5te/binop2addr.S */
6200    /*
6201     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6202     * that specifies an instruction that performs "result = r0 op r1".
6203     * This could be an ARM instruction or a function call.  (If the result
6204     * comes back in a register other than r0, you can override "result".)
6205     *
6206     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6207     * vCC (r1).  Useful for integer division and modulus.
6208     *
6209     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6210     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6211     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6212     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6213     */
6214    /* binop/2addr vA, vB */
6215    mov     r9, rINST, lsr #8           @ r9<- A+
6216    mov     r3, rINST, lsr #12          @ r3<- B
6217    and     r9, r9, #15
6218    GET_VREG(r1, r3)                    @ r1<- vB
6219    GET_VREG(r0, r9)                    @ r0<- vA
6220    .if 0
6221    cmp     r1, #0                      @ is second operand zero?
6222    beq     common_errDivideByZero
6223    .endif
6224    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6225
6226                               @ optional op; may set condition codes
6227    bl      fmodf                              @ r0<- op, r0-r3 changed
6228    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6229    SET_VREG(r0, r9)               @ vAA<- r0
6230    GOTO_OPCODE(ip)                     @ jump to next instruction
6231    /* 10-13 instructions */
6232
6233
6234/* ------------------------------ */
6235    .balign 64
6236.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6237/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6238/* File: arm-vfp/fbinopWide2addr.S */
6239    /*
6240     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6241     * an "instr" line that specifies an instruction that performs
6242     * "d2 = d0 op d1".
6243     *
6244     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6245     *      div-double/2addr
6246     */
6247    /* binop/2addr vA, vB */
6248    mov     r3, rINST, lsr #12          @ r3<- B
6249    mov     r9, rINST, lsr #8           @ r9<- A+
6250    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6251    and     r9, r9, #15                 @ r9<- A
6252    fldd    d1, [r3]                    @ d1<- vB
6253    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6254    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6255    fldd    d0, [r9]                    @ d0<- vA
6256
6257    faddd   d2, d0, d1                              @ d2<- op
6258    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6259    fstd    d2, [r9]                    @ vAA<- d2
6260    GOTO_OPCODE(ip)                     @ jump to next instruction
6261
6262
6263/* ------------------------------ */
6264    .balign 64
6265.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6266/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6267/* File: arm-vfp/fbinopWide2addr.S */
6268    /*
6269     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6270     * an "instr" line that specifies an instruction that performs
6271     * "d2 = d0 op d1".
6272     *
6273     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6274     *      div-double/2addr
6275     */
6276    /* binop/2addr vA, vB */
6277    mov     r3, rINST, lsr #12          @ r3<- B
6278    mov     r9, rINST, lsr #8           @ r9<- A+
6279    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6280    and     r9, r9, #15                 @ r9<- A
6281    fldd    d1, [r3]                    @ d1<- vB
6282    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6283    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6284    fldd    d0, [r9]                    @ d0<- vA
6285
6286    fsubd   d2, d0, d1                              @ d2<- op
6287    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6288    fstd    d2, [r9]                    @ vAA<- d2
6289    GOTO_OPCODE(ip)                     @ jump to next instruction
6290
6291
6292/* ------------------------------ */
6293    .balign 64
6294.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6295/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6296/* File: arm-vfp/fbinopWide2addr.S */
6297    /*
6298     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6299     * an "instr" line that specifies an instruction that performs
6300     * "d2 = d0 op d1".
6301     *
6302     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6303     *      div-double/2addr
6304     */
6305    /* binop/2addr vA, vB */
6306    mov     r3, rINST, lsr #12          @ r3<- B
6307    mov     r9, rINST, lsr #8           @ r9<- A+
6308    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6309    and     r9, r9, #15                 @ r9<- A
6310    fldd    d1, [r3]                    @ d1<- vB
6311    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6312    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6313    fldd    d0, [r9]                    @ d0<- vA
6314
6315    fmuld   d2, d0, d1                              @ d2<- op
6316    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6317    fstd    d2, [r9]                    @ vAA<- d2
6318    GOTO_OPCODE(ip)                     @ jump to next instruction
6319
6320
6321/* ------------------------------ */
6322    .balign 64
6323.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6324/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6325/* File: arm-vfp/fbinopWide2addr.S */
6326    /*
6327     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6328     * an "instr" line that specifies an instruction that performs
6329     * "d2 = d0 op d1".
6330     *
6331     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6332     *      div-double/2addr
6333     */
6334    /* binop/2addr vA, vB */
6335    mov     r3, rINST, lsr #12          @ r3<- B
6336    mov     r9, rINST, lsr #8           @ r9<- A+
6337    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6338    and     r9, r9, #15                 @ r9<- A
6339    fldd    d1, [r3]                    @ d1<- vB
6340    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6341    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6342    fldd    d0, [r9]                    @ d0<- vA
6343
6344    fdivd   d2, d0, d1                              @ d2<- op
6345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6346    fstd    d2, [r9]                    @ vAA<- d2
6347    GOTO_OPCODE(ip)                     @ jump to next instruction
6348
6349
6350/* ------------------------------ */
6351    .balign 64
6352.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6353/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6354/* EABI doesn't define a double remainder function, but libm does */
6355/* File: armv5te/binopWide2addr.S */
6356    /*
6357     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6358     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6359     * This could be an ARM instruction or a function call.  (If the result
6360     * comes back in a register other than r0, you can override "result".)
6361     *
6362     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6363     * vCC (r1).  Useful for integer division and modulus.
6364     *
6365     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6366     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6367     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6368     *      rem-double/2addr
6369     */
6370    /* binop/2addr vA, vB */
6371    mov     r9, rINST, lsr #8           @ r9<- A+
6372    mov     r1, rINST, lsr #12          @ r1<- B
6373    and     r9, r9, #15
6374    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6375    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6376    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6377    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6378    .if 0
6379    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6380    beq     common_errDivideByZero
6381    .endif
6382    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6383
6384                               @ optional op; may set condition codes
6385    bl      fmod                              @ result<- op, r0-r3 changed
6386    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6387    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6388    GOTO_OPCODE(ip)                     @ jump to next instruction
6389    /* 12-15 instructions */
6390
6391
6392/* ------------------------------ */
6393    .balign 64
6394.L_OP_ADD_INT_LIT16: /* 0xd0 */
6395/* File: armv5te/OP_ADD_INT_LIT16.S */
6396/* File: armv5te/binopLit16.S */
6397    /*
6398     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6399     * that specifies an instruction that performs "result = r0 op r1".
6400     * This could be an ARM instruction or a function call.  (If the result
6401     * comes back in a register other than r0, you can override "result".)
6402     *
6403     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6404     * vCC (r1).  Useful for integer division and modulus.
6405     *
6406     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6407     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6408     */
6409    /* binop/lit16 vA, vB, #+CCCC */
6410    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6411    mov     r2, rINST, lsr #12          @ r2<- B
6412    mov     r9, rINST, lsr #8           @ r9<- A+
6413    GET_VREG(r0, r2)                    @ r0<- vB
6414    and     r9, r9, #15
6415    .if 0
6416    cmp     r1, #0                      @ is second operand zero?
6417    beq     common_errDivideByZero
6418    .endif
6419    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6420
6421    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6423    SET_VREG(r0, r9)               @ vAA<- r0
6424    GOTO_OPCODE(ip)                     @ jump to next instruction
6425    /* 10-13 instructions */
6426
6427
6428/* ------------------------------ */
6429    .balign 64
6430.L_OP_RSUB_INT: /* 0xd1 */
6431/* File: armv5te/OP_RSUB_INT.S */
6432/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6433/* File: armv5te/binopLit16.S */
6434    /*
6435     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6436     * that specifies an instruction that performs "result = r0 op r1".
6437     * This could be an ARM instruction or a function call.  (If the result
6438     * comes back in a register other than r0, you can override "result".)
6439     *
6440     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6441     * vCC (r1).  Useful for integer division and modulus.
6442     *
6443     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6444     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6445     */
6446    /* binop/lit16 vA, vB, #+CCCC */
6447    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6448    mov     r2, rINST, lsr #12          @ r2<- B
6449    mov     r9, rINST, lsr #8           @ r9<- A+
6450    GET_VREG(r0, r2)                    @ r0<- vB
6451    and     r9, r9, #15
6452    .if 0
6453    cmp     r1, #0                      @ is second operand zero?
6454    beq     common_errDivideByZero
6455    .endif
6456    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6457
6458    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6459    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6460    SET_VREG(r0, r9)               @ vAA<- r0
6461    GOTO_OPCODE(ip)                     @ jump to next instruction
6462    /* 10-13 instructions */
6463
6464
6465/* ------------------------------ */
6466    .balign 64
6467.L_OP_MUL_INT_LIT16: /* 0xd2 */
6468/* File: armv5te/OP_MUL_INT_LIT16.S */
6469/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6470/* File: armv5te/binopLit16.S */
6471    /*
6472     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6473     * that specifies an instruction that performs "result = r0 op r1".
6474     * This could be an ARM instruction or a function call.  (If the result
6475     * comes back in a register other than r0, you can override "result".)
6476     *
6477     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6478     * vCC (r1).  Useful for integer division and modulus.
6479     *
6480     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6481     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6482     */
6483    /* binop/lit16 vA, vB, #+CCCC */
6484    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6485    mov     r2, rINST, lsr #12          @ r2<- B
6486    mov     r9, rINST, lsr #8           @ r9<- A+
6487    GET_VREG(r0, r2)                    @ r0<- vB
6488    and     r9, r9, #15
6489    .if 0
6490    cmp     r1, #0                      @ is second operand zero?
6491    beq     common_errDivideByZero
6492    .endif
6493    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6494
6495    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6496    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6497    SET_VREG(r0, r9)               @ vAA<- r0
6498    GOTO_OPCODE(ip)                     @ jump to next instruction
6499    /* 10-13 instructions */
6500
6501
6502/* ------------------------------ */
6503    .balign 64
6504.L_OP_DIV_INT_LIT16: /* 0xd3 */
6505/* File: armv5te/OP_DIV_INT_LIT16.S */
6506/* File: armv5te/binopLit16.S */
6507    /*
6508     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6509     * that specifies an instruction that performs "result = r0 op r1".
6510     * This could be an ARM instruction or a function call.  (If the result
6511     * comes back in a register other than r0, you can override "result".)
6512     *
6513     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6514     * vCC (r1).  Useful for integer division and modulus.
6515     *
6516     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6517     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6518     */
6519    /* binop/lit16 vA, vB, #+CCCC */
6520    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6521    mov     r2, rINST, lsr #12          @ r2<- B
6522    mov     r9, rINST, lsr #8           @ r9<- A+
6523    GET_VREG(r0, r2)                    @ r0<- vB
6524    and     r9, r9, #15
6525    .if 1
6526    cmp     r1, #0                      @ is second operand zero?
6527    beq     common_errDivideByZero
6528    .endif
6529    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6530
6531    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6532    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6533    SET_VREG(r0, r9)               @ vAA<- r0
6534    GOTO_OPCODE(ip)                     @ jump to next instruction
6535    /* 10-13 instructions */
6536
6537
6538/* ------------------------------ */
6539    .balign 64
6540.L_OP_REM_INT_LIT16: /* 0xd4 */
6541/* File: armv5te/OP_REM_INT_LIT16.S */
6542/* idivmod returns quotient in r0 and remainder in r1 */
6543/* File: armv5te/binopLit16.S */
6544    /*
6545     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6546     * that specifies an instruction that performs "result = r0 op r1".
6547     * This could be an ARM instruction or a function call.  (If the result
6548     * comes back in a register other than r0, you can override "result".)
6549     *
6550     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6551     * vCC (r1).  Useful for integer division and modulus.
6552     *
6553     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6554     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6555     */
6556    /* binop/lit16 vA, vB, #+CCCC */
6557    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6558    mov     r2, rINST, lsr #12          @ r2<- B
6559    mov     r9, rINST, lsr #8           @ r9<- A+
6560    GET_VREG(r0, r2)                    @ r0<- vB
6561    and     r9, r9, #15
6562    .if 1
6563    cmp     r1, #0                      @ is second operand zero?
6564    beq     common_errDivideByZero
6565    .endif
6566    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6567
6568    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6569    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6570    SET_VREG(r1, r9)               @ vAA<- r1
6571    GOTO_OPCODE(ip)                     @ jump to next instruction
6572    /* 10-13 instructions */
6573
6574
6575/* ------------------------------ */
6576    .balign 64
6577.L_OP_AND_INT_LIT16: /* 0xd5 */
6578/* File: armv5te/OP_AND_INT_LIT16.S */
6579/* File: armv5te/binopLit16.S */
6580    /*
6581     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6582     * that specifies an instruction that performs "result = r0 op r1".
6583     * This could be an ARM instruction or a function call.  (If the result
6584     * comes back in a register other than r0, you can override "result".)
6585     *
6586     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6587     * vCC (r1).  Useful for integer division and modulus.
6588     *
6589     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6590     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6591     */
6592    /* binop/lit16 vA, vB, #+CCCC */
6593    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6594    mov     r2, rINST, lsr #12          @ r2<- B
6595    mov     r9, rINST, lsr #8           @ r9<- A+
6596    GET_VREG(r0, r2)                    @ r0<- vB
6597    and     r9, r9, #15
6598    .if 0
6599    cmp     r1, #0                      @ is second operand zero?
6600    beq     common_errDivideByZero
6601    .endif
6602    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6603
6604    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6605    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6606    SET_VREG(r0, r9)               @ vAA<- r0
6607    GOTO_OPCODE(ip)                     @ jump to next instruction
6608    /* 10-13 instructions */
6609
6610
6611/* ------------------------------ */
6612    .balign 64
6613.L_OP_OR_INT_LIT16: /* 0xd6 */
6614/* File: armv5te/OP_OR_INT_LIT16.S */
6615/* File: armv5te/binopLit16.S */
6616    /*
6617     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6618     * that specifies an instruction that performs "result = r0 op r1".
6619     * This could be an ARM instruction or a function call.  (If the result
6620     * comes back in a register other than r0, you can override "result".)
6621     *
6622     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6623     * vCC (r1).  Useful for integer division and modulus.
6624     *
6625     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6626     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6627     */
6628    /* binop/lit16 vA, vB, #+CCCC */
6629    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6630    mov     r2, rINST, lsr #12          @ r2<- B
6631    mov     r9, rINST, lsr #8           @ r9<- A+
6632    GET_VREG(r0, r2)                    @ r0<- vB
6633    and     r9, r9, #15
6634    .if 0
6635    cmp     r1, #0                      @ is second operand zero?
6636    beq     common_errDivideByZero
6637    .endif
6638    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6639
6640    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6642    SET_VREG(r0, r9)               @ vAA<- r0
6643    GOTO_OPCODE(ip)                     @ jump to next instruction
6644    /* 10-13 instructions */
6645
6646
6647/* ------------------------------ */
6648    .balign 64
6649.L_OP_XOR_INT_LIT16: /* 0xd7 */
6650/* File: armv5te/OP_XOR_INT_LIT16.S */
6651/* File: armv5te/binopLit16.S */
6652    /*
6653     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6654     * that specifies an instruction that performs "result = r0 op r1".
6655     * This could be an ARM instruction or a function call.  (If the result
6656     * comes back in a register other than r0, you can override "result".)
6657     *
6658     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6659     * vCC (r1).  Useful for integer division and modulus.
6660     *
6661     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6662     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6663     */
6664    /* binop/lit16 vA, vB, #+CCCC */
6665    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6666    mov     r2, rINST, lsr #12          @ r2<- B
6667    mov     r9, rINST, lsr #8           @ r9<- A+
6668    GET_VREG(r0, r2)                    @ r0<- vB
6669    and     r9, r9, #15
6670    .if 0
6671    cmp     r1, #0                      @ is second operand zero?
6672    beq     common_errDivideByZero
6673    .endif
6674    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6675
6676    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6677    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6678    SET_VREG(r0, r9)               @ vAA<- r0
6679    GOTO_OPCODE(ip)                     @ jump to next instruction
6680    /* 10-13 instructions */
6681
6682
6683/* ------------------------------ */
6684    .balign 64
6685.L_OP_ADD_INT_LIT8: /* 0xd8 */
6686/* File: armv5te/OP_ADD_INT_LIT8.S */
6687/* File: armv5te/binopLit8.S */
6688    /*
6689     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6690     * that specifies an instruction that performs "result = r0 op r1".
6691     * This could be an ARM instruction or a function call.  (If the result
6692     * comes back in a register other than r0, you can override "result".)
6693     *
6694     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6695     * vCC (r1).  Useful for integer division and modulus.
6696     *
6697     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6698     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6699     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6700     */
6701    /* binop/lit8 vAA, vBB, #+CC */
6702    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6703    mov     r9, rINST, lsr #8           @ r9<- AA
6704    and     r2, r3, #255                @ r2<- BB
6705    GET_VREG(r0, r2)                    @ r0<- vBB
6706    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6707    .if 0
6708    @cmp     r1, #0                      @ is second operand zero?
6709    beq     common_errDivideByZero
6710    .endif
6711    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6712
6713                               @ optional op; may set condition codes
6714    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6715    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6716    SET_VREG(r0, r9)               @ vAA<- r0
6717    GOTO_OPCODE(ip)                     @ jump to next instruction
6718    /* 10-12 instructions */
6719
6720
6721/* ------------------------------ */
6722    .balign 64
6723.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6724/* File: armv5te/OP_RSUB_INT_LIT8.S */
6725/* File: armv5te/binopLit8.S */
6726    /*
6727     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6728     * that specifies an instruction that performs "result = r0 op r1".
6729     * This could be an ARM instruction or a function call.  (If the result
6730     * comes back in a register other than r0, you can override "result".)
6731     *
6732     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6733     * vCC (r1).  Useful for integer division and modulus.
6734     *
6735     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6736     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6737     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6738     */
6739    /* binop/lit8 vAA, vBB, #+CC */
6740    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6741    mov     r9, rINST, lsr #8           @ r9<- AA
6742    and     r2, r3, #255                @ r2<- BB
6743    GET_VREG(r0, r2)                    @ r0<- vBB
6744    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6745    .if 0
6746    @cmp     r1, #0                      @ is second operand zero?
6747    beq     common_errDivideByZero
6748    .endif
6749    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6750
6751                               @ optional op; may set condition codes
6752    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6753    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6754    SET_VREG(r0, r9)               @ vAA<- r0
6755    GOTO_OPCODE(ip)                     @ jump to next instruction
6756    /* 10-12 instructions */
6757
6758
6759/* ------------------------------ */
6760    .balign 64
6761.L_OP_MUL_INT_LIT8: /* 0xda */
6762/* File: armv5te/OP_MUL_INT_LIT8.S */
6763/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6764/* File: armv5te/binopLit8.S */
6765    /*
6766     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6767     * that specifies an instruction that performs "result = r0 op r1".
6768     * This could be an ARM instruction or a function call.  (If the result
6769     * comes back in a register other than r0, you can override "result".)
6770     *
6771     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6772     * vCC (r1).  Useful for integer division and modulus.
6773     *
6774     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6775     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6776     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6777     */
6778    /* binop/lit8 vAA, vBB, #+CC */
6779    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6780    mov     r9, rINST, lsr #8           @ r9<- AA
6781    and     r2, r3, #255                @ r2<- BB
6782    GET_VREG(r0, r2)                    @ r0<- vBB
6783    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6784    .if 0
6785    @cmp     r1, #0                      @ is second operand zero?
6786    beq     common_errDivideByZero
6787    .endif
6788    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6789
6790                               @ optional op; may set condition codes
6791    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6793    SET_VREG(r0, r9)               @ vAA<- r0
6794    GOTO_OPCODE(ip)                     @ jump to next instruction
6795    /* 10-12 instructions */
6796
6797
6798/* ------------------------------ */
6799    .balign 64
6800.L_OP_DIV_INT_LIT8: /* 0xdb */
6801/* File: armv5te/OP_DIV_INT_LIT8.S */
6802/* File: armv5te/binopLit8.S */
6803    /*
6804     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6805     * that specifies an instruction that performs "result = r0 op r1".
6806     * This could be an ARM instruction or a function call.  (If the result
6807     * comes back in a register other than r0, you can override "result".)
6808     *
6809     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6810     * vCC (r1).  Useful for integer division and modulus.
6811     *
6812     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6813     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6814     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6815     */
6816    /* binop/lit8 vAA, vBB, #+CC */
6817    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6818    mov     r9, rINST, lsr #8           @ r9<- AA
6819    and     r2, r3, #255                @ r2<- BB
6820    GET_VREG(r0, r2)                    @ r0<- vBB
6821    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6822    .if 1
6823    @cmp     r1, #0                      @ is second operand zero?
6824    beq     common_errDivideByZero
6825    .endif
6826    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6827
6828                               @ optional op; may set condition codes
6829    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6830    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6831    SET_VREG(r0, r9)               @ vAA<- r0
6832    GOTO_OPCODE(ip)                     @ jump to next instruction
6833    /* 10-12 instructions */
6834
6835
6836/* ------------------------------ */
6837    .balign 64
6838.L_OP_REM_INT_LIT8: /* 0xdc */
6839/* File: armv5te/OP_REM_INT_LIT8.S */
6840/* idivmod returns quotient in r0 and remainder in r1 */
6841/* File: armv5te/binopLit8.S */
6842    /*
6843     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6844     * that specifies an instruction that performs "result = r0 op r1".
6845     * This could be an ARM instruction or a function call.  (If the result
6846     * comes back in a register other than r0, you can override "result".)
6847     *
6848     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6849     * vCC (r1).  Useful for integer division and modulus.
6850     *
6851     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6852     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6853     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6854     */
6855    /* binop/lit8 vAA, vBB, #+CC */
6856    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6857    mov     r9, rINST, lsr #8           @ r9<- AA
6858    and     r2, r3, #255                @ r2<- BB
6859    GET_VREG(r0, r2)                    @ r0<- vBB
6860    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6861    .if 1
6862    @cmp     r1, #0                      @ is second operand zero?
6863    beq     common_errDivideByZero
6864    .endif
6865    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6866
6867                               @ optional op; may set condition codes
6868    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6869    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6870    SET_VREG(r1, r9)               @ vAA<- r1
6871    GOTO_OPCODE(ip)                     @ jump to next instruction
6872    /* 10-12 instructions */
6873
6874
6875/* ------------------------------ */
6876    .balign 64
6877.L_OP_AND_INT_LIT8: /* 0xdd */
6878/* File: armv5te/OP_AND_INT_LIT8.S */
6879/* File: armv5te/binopLit8.S */
6880    /*
6881     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6882     * that specifies an instruction that performs "result = r0 op r1".
6883     * This could be an ARM instruction or a function call.  (If the result
6884     * comes back in a register other than r0, you can override "result".)
6885     *
6886     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6887     * vCC (r1).  Useful for integer division and modulus.
6888     *
6889     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6890     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6891     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6892     */
6893    /* binop/lit8 vAA, vBB, #+CC */
6894    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6895    mov     r9, rINST, lsr #8           @ r9<- AA
6896    and     r2, r3, #255                @ r2<- BB
6897    GET_VREG(r0, r2)                    @ r0<- vBB
6898    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6899    .if 0
6900    @cmp     r1, #0                      @ is second operand zero?
6901    beq     common_errDivideByZero
6902    .endif
6903    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6904
6905                               @ optional op; may set condition codes
6906    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6908    SET_VREG(r0, r9)               @ vAA<- r0
6909    GOTO_OPCODE(ip)                     @ jump to next instruction
6910    /* 10-12 instructions */
6911
6912
6913/* ------------------------------ */
6914    .balign 64
6915.L_OP_OR_INT_LIT8: /* 0xde */
6916/* File: armv5te/OP_OR_INT_LIT8.S */
6917/* File: armv5te/binopLit8.S */
6918    /*
6919     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6920     * that specifies an instruction that performs "result = r0 op r1".
6921     * This could be an ARM instruction or a function call.  (If the result
6922     * comes back in a register other than r0, you can override "result".)
6923     *
6924     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6925     * vCC (r1).  Useful for integer division and modulus.
6926     *
6927     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6928     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6929     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6930     */
6931    /* binop/lit8 vAA, vBB, #+CC */
6932    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6933    mov     r9, rINST, lsr #8           @ r9<- AA
6934    and     r2, r3, #255                @ r2<- BB
6935    GET_VREG(r0, r2)                    @ r0<- vBB
6936    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6937    .if 0
6938    @cmp     r1, #0                      @ is second operand zero?
6939    beq     common_errDivideByZero
6940    .endif
6941    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6942
6943                               @ optional op; may set condition codes
6944    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6945    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6946    SET_VREG(r0, r9)               @ vAA<- r0
6947    GOTO_OPCODE(ip)                     @ jump to next instruction
6948    /* 10-12 instructions */
6949
6950
6951/* ------------------------------ */
6952    .balign 64
6953.L_OP_XOR_INT_LIT8: /* 0xdf */
6954/* File: armv5te/OP_XOR_INT_LIT8.S */
6955/* File: armv5te/binopLit8.S */
6956    /*
6957     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6958     * that specifies an instruction that performs "result = r0 op r1".
6959     * This could be an ARM instruction or a function call.  (If the result
6960     * comes back in a register other than r0, you can override "result".)
6961     *
6962     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6963     * vCC (r1).  Useful for integer division and modulus.
6964     *
6965     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6966     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6967     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6968     */
6969    /* binop/lit8 vAA, vBB, #+CC */
6970    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6971    mov     r9, rINST, lsr #8           @ r9<- AA
6972    and     r2, r3, #255                @ r2<- BB
6973    GET_VREG(r0, r2)                    @ r0<- vBB
6974    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6975    .if 0
6976    @cmp     r1, #0                      @ is second operand zero?
6977    beq     common_errDivideByZero
6978    .endif
6979    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6980
6981                               @ optional op; may set condition codes
6982    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6983    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6984    SET_VREG(r0, r9)               @ vAA<- r0
6985    GOTO_OPCODE(ip)                     @ jump to next instruction
6986    /* 10-12 instructions */
6987
6988
6989/* ------------------------------ */
6990    .balign 64
6991.L_OP_SHL_INT_LIT8: /* 0xe0 */
6992/* File: armv5te/OP_SHL_INT_LIT8.S */
6993/* File: armv5te/binopLit8.S */
6994    /*
6995     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6996     * that specifies an instruction that performs "result = r0 op r1".
6997     * This could be an ARM instruction or a function call.  (If the result
6998     * comes back in a register other than r0, you can override "result".)
6999     *
7000     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7001     * vCC (r1).  Useful for integer division and modulus.
7002     *
7003     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7004     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7005     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7006     */
7007    /* binop/lit8 vAA, vBB, #+CC */
7008    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7009    mov     r9, rINST, lsr #8           @ r9<- AA
7010    and     r2, r3, #255                @ r2<- BB
7011    GET_VREG(r0, r2)                    @ r0<- vBB
7012    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7013    .if 0
7014    @cmp     r1, #0                      @ is second operand zero?
7015    beq     common_errDivideByZero
7016    .endif
7017    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7018
7019    and     r1, r1, #31                           @ optional op; may set condition codes
7020    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7021    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7022    SET_VREG(r0, r9)               @ vAA<- r0
7023    GOTO_OPCODE(ip)                     @ jump to next instruction
7024    /* 10-12 instructions */
7025
7026
7027/* ------------------------------ */
7028    .balign 64
7029.L_OP_SHR_INT_LIT8: /* 0xe1 */
7030/* File: armv5te/OP_SHR_INT_LIT8.S */
7031/* File: armv5te/binopLit8.S */
7032    /*
7033     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7034     * that specifies an instruction that performs "result = r0 op r1".
7035     * This could be an ARM instruction or a function call.  (If the result
7036     * comes back in a register other than r0, you can override "result".)
7037     *
7038     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7039     * vCC (r1).  Useful for integer division and modulus.
7040     *
7041     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7042     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7043     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7044     */
7045    /* binop/lit8 vAA, vBB, #+CC */
7046    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7047    mov     r9, rINST, lsr #8           @ r9<- AA
7048    and     r2, r3, #255                @ r2<- BB
7049    GET_VREG(r0, r2)                    @ r0<- vBB
7050    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7051    .if 0
7052    @cmp     r1, #0                      @ is second operand zero?
7053    beq     common_errDivideByZero
7054    .endif
7055    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7056
7057    and     r1, r1, #31                           @ optional op; may set condition codes
7058    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7059    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7060    SET_VREG(r0, r9)               @ vAA<- r0
7061    GOTO_OPCODE(ip)                     @ jump to next instruction
7062    /* 10-12 instructions */
7063
7064
7065/* ------------------------------ */
7066    .balign 64
7067.L_OP_USHR_INT_LIT8: /* 0xe2 */
7068/* File: armv5te/OP_USHR_INT_LIT8.S */
7069/* File: armv5te/binopLit8.S */
7070    /*
7071     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7072     * that specifies an instruction that performs "result = r0 op r1".
7073     * This could be an ARM instruction or a function call.  (If the result
7074     * comes back in a register other than r0, you can override "result".)
7075     *
7076     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7077     * vCC (r1).  Useful for integer division and modulus.
7078     *
7079     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7080     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7081     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7082     */
7083    /* binop/lit8 vAA, vBB, #+CC */
7084    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7085    mov     r9, rINST, lsr #8           @ r9<- AA
7086    and     r2, r3, #255                @ r2<- BB
7087    GET_VREG(r0, r2)                    @ r0<- vBB
7088    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7089    .if 0
7090    @cmp     r1, #0                      @ is second operand zero?
7091    beq     common_errDivideByZero
7092    .endif
7093    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7094
7095    and     r1, r1, #31                           @ optional op; may set condition codes
7096    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7098    SET_VREG(r0, r9)               @ vAA<- r0
7099    GOTO_OPCODE(ip)                     @ jump to next instruction
7100    /* 10-12 instructions */
7101
7102
7103/* ------------------------------ */
7104    .balign 64
7105.L_OP_IGET_VOLATILE: /* 0xe3 */
7106/* File: armv5te/OP_IGET_VOLATILE.S */
7107/* File: armv5te/OP_IGET.S */
7108    /*
7109     * General 32-bit instance field get.
7110     *
7111     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7112     */
7113    /* op vA, vB, field@CCCC */
7114    mov     r0, rINST, lsr #12          @ r0<- B
7115    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7116    FETCH(r1, 1)                        @ r1<- field ref CCCC
7117    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7118    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7119    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7120    cmp     r0, #0                      @ is resolved entry null?
7121    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
71228:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7123    EXPORT_PC()                         @ resolve() could throw
7124    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7125    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7126    cmp     r0, #0
7127    bne     .LOP_IGET_VOLATILE_finish
7128    b       common_exceptionThrown
7129
7130
7131/* ------------------------------ */
7132    .balign 64
7133.L_OP_IPUT_VOLATILE: /* 0xe4 */
7134/* File: armv5te/OP_IPUT_VOLATILE.S */
7135/* File: armv5te/OP_IPUT.S */
7136    /*
7137     * General 32-bit instance field put.
7138     *
7139     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
7140     */
7141    /* op vA, vB, field@CCCC */
7142    mov     r0, rINST, lsr #12          @ r0<- B
7143    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7144    FETCH(r1, 1)                        @ r1<- field ref CCCC
7145    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7146    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7147    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7148    cmp     r0, #0                      @ is resolved entry null?
7149    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71508:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7151    EXPORT_PC()                         @ resolve() could throw
7152    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7153    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7154    cmp     r0, #0                      @ success?
7155    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7156    b       common_exceptionThrown
7157
7158
7159/* ------------------------------ */
7160    .balign 64
7161.L_OP_SGET_VOLATILE: /* 0xe5 */
7162/* File: armv5te/OP_SGET_VOLATILE.S */
7163/* File: armv5te/OP_SGET.S */
7164    /*
7165     * General 32-bit SGET handler.
7166     *
7167     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7168     */
7169    /* op vAA, field@BBBB */
7170    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7171    FETCH(r1, 1)                        @ r1<- field ref BBBB
7172    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7173    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7174    cmp     r0, #0                      @ is resolved entry null?
7175    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7176.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7177    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7178    SMP_DMB 1                   @ acquiring load
7179    mov     r2, rINST, lsr #8           @ r2<- AA
7180    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7181    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7183    GOTO_OPCODE(ip)                     @ jump to next instruction
7184
7185
7186/* ------------------------------ */
7187    .balign 64
7188.L_OP_SPUT_VOLATILE: /* 0xe6 */
7189/* File: armv5te/OP_SPUT_VOLATILE.S */
7190/* File: armv5te/OP_SPUT.S */
7191    /*
7192     * General 32-bit SPUT handler.
7193     *
7194     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
7195     */
7196    /* op vAA, field@BBBB */
7197    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7198    FETCH(r1, 1)                        @ r1<- field ref BBBB
7199    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7200    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7201    cmp     r0, #0                      @ is resolved entry null?
7202    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7203.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7204    mov     r2, rINST, lsr #8           @ r2<- AA
7205    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7206    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7208    SMP_DMB 1                   @ releasing store
7209    str     r1, [r0, #offStaticField_value] @ field<- vAA
7210    GOTO_OPCODE(ip)                     @ jump to next instruction
7211
7212
7213/* ------------------------------ */
7214    .balign 64
7215.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7216/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7217/* File: armv5te/OP_IGET.S */
7218    /*
7219     * General 32-bit instance field get.
7220     *
7221     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7222     */
7223    /* op vA, vB, field@CCCC */
7224    mov     r0, rINST, lsr #12          @ r0<- B
7225    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7226    FETCH(r1, 1)                        @ r1<- field ref CCCC
7227    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7228    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7229    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7230    cmp     r0, #0                      @ is resolved entry null?
7231    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
72328:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7233    EXPORT_PC()                         @ resolve() could throw
7234    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7235    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7236    cmp     r0, #0
7237    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7238    b       common_exceptionThrown
7239
7240
7241/* ------------------------------ */
7242    .balign 64
7243.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7244/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7245/* File: armv5te/OP_IGET_WIDE.S */
7246    /*
7247     * Wide 32-bit instance field get.
7248     */
7249    /* iget-wide vA, vB, field@CCCC */
7250    mov     r0, rINST, lsr #12          @ r0<- B
7251    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7252    FETCH(r1, 1)                        @ r1<- field ref CCCC
7253    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7254    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7255    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7256    cmp     r0, #0                      @ is resolved entry null?
7257    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72588:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7259    EXPORT_PC()                         @ resolve() could throw
7260    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7261    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7262    cmp     r0, #0
7263    bne     .LOP_IGET_WIDE_VOLATILE_finish
7264    b       common_exceptionThrown
7265
7266
7267/* ------------------------------ */
7268    .balign 64
7269.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7270/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7271/* File: armv5te/OP_IPUT_WIDE.S */
7272    /* iput-wide vA, vB, field@CCCC */
7273    mov     r0, rINST, lsr #12          @ r0<- B
7274    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7275    FETCH(r1, 1)                        @ r1<- field ref CCCC
7276    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7277    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7278    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7279    cmp     r0, #0                      @ is resolved entry null?
7280    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72818:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7282    EXPORT_PC()                         @ resolve() could throw
7283    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7284    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7285    cmp     r0, #0                      @ success?
7286    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7287    b       common_exceptionThrown
7288
7289
7290/* ------------------------------ */
7291    .balign 64
7292.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7293/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7294/* File: armv5te/OP_SGET_WIDE.S */
7295    /*
7296     * 64-bit SGET handler.
7297     */
7298    /* sget-wide vAA, field@BBBB */
7299    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7300    FETCH(r1, 1)                        @ r1<- field ref BBBB
7301    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7302    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7303    cmp     r0, #0                      @ is resolved entry null?
7304    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7305.LOP_SGET_WIDE_VOLATILE_finish:
7306    mov     r9, rINST, lsr #8           @ r9<- AA
7307    .if 1
7308    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7309    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7310    .else
7311    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7312    .endif
7313    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7314    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7315    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7316    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7317    GOTO_OPCODE(ip)                     @ jump to next instruction
7318
7319
7320/* ------------------------------ */
7321    .balign 64
7322.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7323/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7324/* File: armv5te/OP_SPUT_WIDE.S */
7325    /*
7326     * 64-bit SPUT handler.
7327     */
7328    /* sput-wide vAA, field@BBBB */
7329    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7330    FETCH(r1, 1)                        @ r1<- field ref BBBB
7331    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7332    mov     r9, rINST, lsr #8           @ r9<- AA
7333    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7334    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7335    cmp     r2, #0                      @ is resolved entry null?
7336    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7337.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7338    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7339    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7340    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7341    .if 1
7342    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7343    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7344    .else
7345    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7346    .endif
7347    GOTO_OPCODE(r10)                    @ jump to next instruction
7348
7349
7350/* ------------------------------ */
7351    .balign 64
7352.L_OP_BREAKPOINT: /* 0xec */
7353/* File: armv5te/OP_BREAKPOINT.S */
7354/* File: armv5te/unused.S */
7355    bl      common_abort
7356
7357
7358/* ------------------------------ */
7359    .balign 64
7360.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7361/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7362    /*
7363     * Handle a throw-verification-error instruction.  This throws an
7364     * exception for an error discovered during verification.  The
7365     * exception is indicated by AA, with some detail provided by BBBB.
7366     */
7367    /* op AA, ref@BBBB */
7368    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7369    FETCH(r2, 1)                        @ r2<- BBBB
7370    EXPORT_PC()                         @ export the PC
7371    mov     r1, rINST, lsr #8           @ r1<- AA
7372    bl      dvmThrowVerificationError   @ always throws
7373    b       common_exceptionThrown      @ handle exception
7374
7375/* ------------------------------ */
7376    .balign 64
7377.L_OP_EXECUTE_INLINE: /* 0xee */
7378/* File: armv5te/OP_EXECUTE_INLINE.S */
7379    /*
7380     * Execute a "native inline" instruction.
7381     *
7382     * We need to call an InlineOp4Func:
7383     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7384     *
7385     * The first four args are in r0-r3, pointer to return value storage
7386     * is on the stack.  The function's return value is a flag that tells
7387     * us if an exception was thrown.
7388     */
7389    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7390    FETCH(r10, 1)                       @ r10<- BBBB
7391    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7392    EXPORT_PC()                         @ can throw
7393    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7394    mov     r0, rINST, lsr #12          @ r0<- B
7395    str     r1, [sp]                    @ push &glue->retval
7396    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7397    add     sp, sp, #8                  @ pop stack
7398    cmp     r0, #0                      @ test boolean result of inline
7399    beq     common_exceptionThrown      @ returned false, handle exception
7400    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7401    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7402    GOTO_OPCODE(ip)                     @ jump to next instruction
7403
7404/* ------------------------------ */
7405    .balign 64
7406.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7407/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7408    /*
7409     * Execute a "native inline" instruction, using "/range" semantics.
7410     * Same idea as execute-inline, but we get the args differently.
7411     *
7412     * We need to call an InlineOp4Func:
7413     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7414     *
7415     * The first four args are in r0-r3, pointer to return value storage
7416     * is on the stack.  The function's return value is a flag that tells
7417     * us if an exception was thrown.
7418     */
7419    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7420    FETCH(r10, 1)                       @ r10<- BBBB
7421    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7422    EXPORT_PC()                         @ can throw
7423    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7424    mov     r0, rINST, lsr #8           @ r0<- AA
7425    str     r1, [sp]                    @ push &glue->retval
7426    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7427    add     sp, sp, #8                  @ pop stack
7428    cmp     r0, #0                      @ test boolean result of inline
7429    beq     common_exceptionThrown      @ returned false, handle exception
7430    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7431    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7432    GOTO_OPCODE(ip)                     @ jump to next instruction
7433
7434/* ------------------------------ */
7435    .balign 64
7436.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7437/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7438    /*
7439     * invoke-direct-empty is a no-op in a "standard" interpreter.
7440     */
7441    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7442    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7443    GOTO_OPCODE(ip)                     @ execute it
7444
7445/* ------------------------------ */
7446    .balign 64
7447.L_OP_UNUSED_F1: /* 0xf1 */
7448/* File: armv5te/OP_UNUSED_F1.S */
7449/* File: armv5te/unused.S */
7450    bl      common_abort
7451
7452
7453/* ------------------------------ */
7454    .balign 64
7455.L_OP_IGET_QUICK: /* 0xf2 */
7456/* File: armv5te/OP_IGET_QUICK.S */
7457    /* For: iget-quick, iget-object-quick */
7458    /* op vA, vB, offset@CCCC */
7459    mov     r2, rINST, lsr #12          @ r2<- B
7460    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7461    FETCH(r1, 1)                        @ r1<- field byte offset
7462    cmp     r3, #0                      @ check object for null
7463    mov     r2, rINST, lsr #8           @ r2<- A(+)
7464    beq     common_errNullObject        @ object was null
7465    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7466    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7467    and     r2, r2, #15
7468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7469    SET_VREG(r0, r2)                    @ fp[A]<- r0
7470    GOTO_OPCODE(ip)                     @ jump to next instruction
7471
7472/* ------------------------------ */
7473    .balign 64
7474.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7475/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7476    /* iget-wide-quick vA, vB, offset@CCCC */
7477    mov     r2, rINST, lsr #12          @ r2<- B
7478    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7479    FETCH(ip, 1)                        @ ip<- field byte offset
7480    cmp     r3, #0                      @ check object for null
7481    mov     r2, rINST, lsr #8           @ r2<- A(+)
7482    beq     common_errNullObject        @ object was null
7483    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7484    and     r2, r2, #15
7485    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7486    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7487    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7488    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7489    GOTO_OPCODE(ip)                     @ jump to next instruction
7490
7491/* ------------------------------ */
7492    .balign 64
7493.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7494/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7495/* File: armv5te/OP_IGET_QUICK.S */
7496    /* For: iget-quick, iget-object-quick */
7497    /* op vA, vB, offset@CCCC */
7498    mov     r2, rINST, lsr #12          @ r2<- B
7499    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7500    FETCH(r1, 1)                        @ r1<- field byte offset
7501    cmp     r3, #0                      @ check object for null
7502    mov     r2, rINST, lsr #8           @ r2<- A(+)
7503    beq     common_errNullObject        @ object was null
7504    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7505    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7506    and     r2, r2, #15
7507    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7508    SET_VREG(r0, r2)                    @ fp[A]<- r0
7509    GOTO_OPCODE(ip)                     @ jump to next instruction
7510
7511
7512/* ------------------------------ */
7513    .balign 64
7514.L_OP_IPUT_QUICK: /* 0xf5 */
7515/* File: armv5te/OP_IPUT_QUICK.S */
7516    /* For: iput-quick, iput-object-quick */
7517    /* op vA, vB, offset@CCCC */
7518    mov     r2, rINST, lsr #12          @ r2<- B
7519    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7520    FETCH(r1, 1)                        @ r1<- field byte offset
7521    cmp     r3, #0                      @ check object for null
7522    mov     r2, rINST, lsr #8           @ r2<- A(+)
7523    beq     common_errNullObject        @ object was null
7524    and     r2, r2, #15
7525    GET_VREG(r0, r2)                    @ r0<- fp[A]
7526    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7527    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7528    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7529    GOTO_OPCODE(ip)                     @ jump to next instruction
7530
7531/* ------------------------------ */
7532    .balign 64
7533.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7534/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7535    /* iput-wide-quick vA, vB, offset@CCCC */
7536    mov     r0, rINST, lsr #8           @ r0<- A(+)
7537    mov     r1, rINST, lsr #12          @ r1<- B
7538    and     r0, r0, #15
7539    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7540    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7541    cmp     r2, #0                      @ check object for null
7542    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7543    beq     common_errNullObject        @ object was null
7544    FETCH(r3, 1)                        @ r3<- field byte offset
7545    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7546    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7547    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7548    GOTO_OPCODE(ip)                     @ jump to next instruction
7549
7550/* ------------------------------ */
7551    .balign 64
7552.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7553/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7554/* File: armv5te/OP_IPUT_QUICK.S */
7555    /* For: iput-quick, iput-object-quick */
7556    /* op vA, vB, offset@CCCC */
7557    mov     r2, rINST, lsr #12          @ r2<- B
7558    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7559    FETCH(r1, 1)                        @ r1<- field byte offset
7560    cmp     r3, #0                      @ check object for null
7561    mov     r2, rINST, lsr #8           @ r2<- A(+)
7562    beq     common_errNullObject        @ object was null
7563    and     r2, r2, #15
7564    GET_VREG(r0, r2)                    @ r0<- fp[A]
7565    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7566    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7568    GOTO_OPCODE(ip)                     @ jump to next instruction
7569
7570
7571/* ------------------------------ */
7572    .balign 64
7573.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7574/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7575    /*
7576     * Handle an optimized virtual method call.
7577     *
7578     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7579     */
7580    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7581    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7582    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7583    FETCH(r1, 1)                        @ r1<- BBBB
7584    .if     (!0)
7585    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7586    .endif
7587    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7588    cmp     r2, #0                      @ is "this" null?
7589    beq     common_errNullObject        @ null "this", throw exception
7590    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7591    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7592    EXPORT_PC()                         @ invoke must export
7593    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7594    bl      common_invokeMethodNoRange @ continue on
7595
7596/* ------------------------------ */
7597    .balign 64
7598.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7599/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7600/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7601    /*
7602     * Handle an optimized virtual method call.
7603     *
7604     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7605     */
7606    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7607    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7608    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7609    FETCH(r1, 1)                        @ r1<- BBBB
7610    .if     (!1)
7611    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7612    .endif
7613    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7614    cmp     r2, #0                      @ is "this" null?
7615    beq     common_errNullObject        @ null "this", throw exception
7616    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7617    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7618    EXPORT_PC()                         @ invoke must export
7619    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7620    bl      common_invokeMethodRange @ continue on
7621
7622
7623/* ------------------------------ */
7624    .balign 64
7625.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7626/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7627    /*
7628     * Handle an optimized "super" method call.
7629     *
7630     * for: [opt] invoke-super-quick, invoke-super-quick/range
7631     */
7632    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7633    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7634    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7635    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7636    .if     (!0)
7637    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7638    .endif
7639    FETCH(r1, 1)                        @ r1<- BBBB
7640    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7641    EXPORT_PC()                         @ must export for invoke
7642    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7643    GET_VREG(r3, r10)                   @ r3<- "this"
7644    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7645    cmp     r3, #0                      @ null "this" ref?
7646    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7647    beq     common_errNullObject        @ "this" is null, throw exception
7648    bl      common_invokeMethodNoRange @ continue on
7649
7650/* ------------------------------ */
7651    .balign 64
7652.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7653/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7654/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7655    /*
7656     * Handle an optimized "super" method call.
7657     *
7658     * for: [opt] invoke-super-quick, invoke-super-quick/range
7659     */
7660    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7661    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7662    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7663    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7664    .if     (!1)
7665    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7666    .endif
7667    FETCH(r1, 1)                        @ r1<- BBBB
7668    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7669    EXPORT_PC()                         @ must export for invoke
7670    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7671    GET_VREG(r3, r10)                   @ r3<- "this"
7672    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7673    cmp     r3, #0                      @ null "this" ref?
7674    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7675    beq     common_errNullObject        @ "this" is null, throw exception
7676    bl      common_invokeMethodRange @ continue on
7677
7678
7679/* ------------------------------ */
7680    .balign 64
7681.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7682/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7683/* File: armv5te/OP_IPUT.S */
7684    /*
7685     * General 32-bit instance field put.
7686     *
7687     * for: iput, iput-object, iput-boolean, iput-byte, iput-char, iput-short
7688     */
7689    /* op vA, vB, field@CCCC */
7690    mov     r0, rINST, lsr #12          @ r0<- B
7691    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7692    FETCH(r1, 1)                        @ r1<- field ref CCCC
7693    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7694    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7695    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7696    cmp     r0, #0                      @ is resolved entry null?
7697    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
76988:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7699    EXPORT_PC()                         @ resolve() could throw
7700    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7701    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7702    cmp     r0, #0                      @ success?
7703    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7704    b       common_exceptionThrown
7705
7706
7707/* ------------------------------ */
7708    .balign 64
7709.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7710/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7711/* File: armv5te/OP_SGET.S */
7712    /*
7713     * General 32-bit SGET handler.
7714     *
7715     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7716     */
7717    /* op vAA, field@BBBB */
7718    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7719    FETCH(r1, 1)                        @ r1<- field ref BBBB
7720    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7721    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7722    cmp     r0, #0                      @ is resolved entry null?
7723    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7724.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7725    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7726    SMP_DMB 1                   @ acquiring load
7727    mov     r2, rINST, lsr #8           @ r2<- AA
7728    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7729    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7731    GOTO_OPCODE(ip)                     @ jump to next instruction
7732
7733
7734/* ------------------------------ */
7735    .balign 64
7736.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7737/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7738/* File: armv5te/OP_SPUT.S */
7739    /*
7740     * General 32-bit SPUT handler.
7741     *
7742     * for: sput, sput-object, sput-boolean, sput-byte, sput-char, sput-short
7743     */
7744    /* op vAA, field@BBBB */
7745    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7746    FETCH(r1, 1)                        @ r1<- field ref BBBB
7747    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7748    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7749    cmp     r0, #0                      @ is resolved entry null?
7750    beq     .LOP_SPUT_OBJECT_VOLATILE_resolve         @ yes, do resolve
7751.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
7752    mov     r2, rINST, lsr #8           @ r2<- AA
7753    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7754    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7755    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7756    SMP_DMB 1                   @ releasing store
7757    str     r1, [r0, #offStaticField_value] @ field<- vAA
7758    GOTO_OPCODE(ip)                     @ jump to next instruction
7759
7760
7761/* ------------------------------ */
7762    .balign 64
7763.L_OP_UNUSED_FF: /* 0xff */
7764/* File: armv5te/OP_UNUSED_FF.S */
7765/* File: armv5te/unused.S */
7766    bl      common_abort
7767
7768
7769
7770    .balign 64
7771    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7772    .global dvmAsmInstructionEnd
7773dvmAsmInstructionEnd:
7774
7775/*
7776 * ===========================================================================
7777 *  Sister implementations
7778 * ===========================================================================
7779 */
7780    .global dvmAsmSisterStart
7781    .type   dvmAsmSisterStart, %function
7782    .text
7783    .balign 4
7784dvmAsmSisterStart:
7785
7786/* continuation for OP_CONST_STRING */
7787
7788    /*
7789     * Continuation if the String has not yet been resolved.
7790     *  r1: BBBB (String ref)
7791     *  r9: target register
7792     */
7793.LOP_CONST_STRING_resolve:
7794    EXPORT_PC()
7795    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7796    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7797    bl      dvmResolveString            @ r0<- String reference
7798    cmp     r0, #0                      @ failed?
7799    beq     common_exceptionThrown      @ yup, handle the exception
7800    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7802    SET_VREG(r0, r9)                    @ vAA<- r0
7803    GOTO_OPCODE(ip)                     @ jump to next instruction
7804
7805/* continuation for OP_CONST_STRING_JUMBO */
7806
7807    /*
7808     * Continuation if the String has not yet been resolved.
7809     *  r1: BBBBBBBB (String ref)
7810     *  r9: target register
7811     */
7812.LOP_CONST_STRING_JUMBO_resolve:
7813    EXPORT_PC()
7814    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7815    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7816    bl      dvmResolveString            @ r0<- String reference
7817    cmp     r0, #0                      @ failed?
7818    beq     common_exceptionThrown      @ yup, handle the exception
7819    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7820    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7821    SET_VREG(r0, r9)                    @ vAA<- r0
7822    GOTO_OPCODE(ip)                     @ jump to next instruction
7823
7824/* continuation for OP_CONST_CLASS */
7825
7826    /*
7827     * Continuation if the Class has not yet been resolved.
7828     *  r1: BBBB (Class ref)
7829     *  r9: target register
7830     */
7831.LOP_CONST_CLASS_resolve:
7832    EXPORT_PC()
7833    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7834    mov     r2, #1                      @ r2<- true
7835    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7836    bl      dvmResolveClass             @ r0<- Class reference
7837    cmp     r0, #0                      @ failed?
7838    beq     common_exceptionThrown      @ yup, handle the exception
7839    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7841    SET_VREG(r0, r9)                    @ vAA<- r0
7842    GOTO_OPCODE(ip)                     @ jump to next instruction
7843
7844/* continuation for OP_CHECK_CAST */
7845
7846    /*
7847     * Trivial test failed, need to perform full check.  This is common.
7848     *  r0 holds obj->clazz
7849     *  r1 holds class resolved from BBBB
7850     *  r9 holds object
7851     */
7852.LOP_CHECK_CAST_fullcheck:
7853    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7854    cmp     r0, #0                      @ failed?
7855    bne     .LOP_CHECK_CAST_okay            @ no, success
7856
7857    @ A cast has failed.  We need to throw a ClassCastException with the
7858    @ class of the object that failed to be cast.
7859    EXPORT_PC()                         @ about to throw
7860    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7861    ldr     r0, .LstrClassCastExceptionPtr
7862    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7863    bl      dvmThrowExceptionWithClassMessage
7864    b       common_exceptionThrown
7865
7866    /*
7867     * Resolution required.  This is the least-likely path.
7868     *
7869     *  r2 holds BBBB
7870     *  r9 holds object
7871     */
7872.LOP_CHECK_CAST_resolve:
7873    EXPORT_PC()                         @ resolve() could throw
7874    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7875    mov     r1, r2                      @ r1<- BBBB
7876    mov     r2, #0                      @ r2<- false
7877    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7878    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7879    cmp     r0, #0                      @ got null?
7880    beq     common_exceptionThrown      @ yes, handle exception
7881    mov     r1, r0                      @ r1<- class resolved from BBB
7882    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7883    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7884
7885.LstrClassCastExceptionPtr:
7886    .word   .LstrClassCastException
7887
7888/* continuation for OP_INSTANCE_OF */
7889
7890    /*
7891     * Trivial test failed, need to perform full check.  This is common.
7892     *  r0 holds obj->clazz
7893     *  r1 holds class resolved from BBBB
7894     *  r9 holds A
7895     */
7896.LOP_INSTANCE_OF_fullcheck:
7897    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7898    @ fall through to OP_INSTANCE_OF_store
7899
7900    /*
7901     * r0 holds boolean result
7902     * r9 holds A
7903     */
7904.LOP_INSTANCE_OF_store:
7905    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7906    SET_VREG(r0, r9)                    @ vA<- r0
7907    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7908    GOTO_OPCODE(ip)                     @ jump to next instruction
7909
7910    /*
7911     * Trivial test succeeded, save and bail.
7912     *  r9 holds A
7913     */
7914.LOP_INSTANCE_OF_trivial:
7915    mov     r0, #1                      @ indicate success
7916    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7917    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7918    SET_VREG(r0, r9)                    @ vA<- r0
7919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7920    GOTO_OPCODE(ip)                     @ jump to next instruction
7921
7922    /*
7923     * Resolution required.  This is the least-likely path.
7924     *
7925     *  r3 holds BBBB
7926     *  r9 holds A
7927     */
7928.LOP_INSTANCE_OF_resolve:
7929    EXPORT_PC()                         @ resolve() could throw
7930    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7931    mov     r1, r3                      @ r1<- BBBB
7932    mov     r2, #1                      @ r2<- true
7933    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7934    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7935    cmp     r0, #0                      @ got null?
7936    beq     common_exceptionThrown      @ yes, handle exception
7937    mov     r1, r0                      @ r1<- class resolved from BBB
7938    mov     r3, rINST, lsr #12          @ r3<- B
7939    GET_VREG(r0, r3)                    @ r0<- vB (object)
7940    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7941    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7942
7943/* continuation for OP_NEW_INSTANCE */
7944
7945    .balign 32                          @ minimize cache lines
7946.LOP_NEW_INSTANCE_finish: @ r0=new object
7947    mov     r3, rINST, lsr #8           @ r3<- AA
7948    cmp     r0, #0                      @ failed?
7949    beq     common_exceptionThrown      @ yes, handle the exception
7950    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7951    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7952    SET_VREG(r0, r3)                    @ vAA<- r0
7953    GOTO_OPCODE(ip)                     @ jump to next instruction
7954
7955    /*
7956     * Class initialization required.
7957     *
7958     *  r0 holds class object
7959     */
7960.LOP_NEW_INSTANCE_needinit:
7961    mov     r9, r0                      @ save r0
7962    bl      dvmInitClass                @ initialize class
7963    cmp     r0, #0                      @ check boolean result
7964    mov     r0, r9                      @ restore r0
7965    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7966    b       common_exceptionThrown      @ failed, deal with init exception
7967
7968    /*
7969     * Resolution required.  This is the least-likely path.
7970     *
7971     *  r1 holds BBBB
7972     */
7973.LOP_NEW_INSTANCE_resolve:
7974    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7975    mov     r2, #0                      @ r2<- false
7976    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7977    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7978    cmp     r0, #0                      @ got null?
7979    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7980    b       common_exceptionThrown      @ yes, handle exception
7981
7982.LstrInstantiationErrorPtr:
7983    .word   .LstrInstantiationError
7984
7985/* continuation for OP_NEW_ARRAY */
7986
7987
7988    /*
7989     * Resolve class.  (This is an uncommon case.)
7990     *
7991     *  r1 holds array length
7992     *  r2 holds class ref CCCC
7993     */
7994.LOP_NEW_ARRAY_resolve:
7995    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7996    mov     r9, r1                      @ r9<- length (save)
7997    mov     r1, r2                      @ r1<- CCCC
7998    mov     r2, #0                      @ r2<- false
7999    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8000    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8001    cmp     r0, #0                      @ got null?
8002    mov     r1, r9                      @ r1<- length (restore)
8003    beq     common_exceptionThrown      @ yes, handle exception
8004    @ fall through to OP_NEW_ARRAY_finish
8005
8006    /*
8007     * Finish allocation.
8008     *
8009     *  r0 holds class
8010     *  r1 holds array length
8011     */
8012.LOP_NEW_ARRAY_finish:
8013    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8014    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8015    cmp     r0, #0                      @ failed?
8016    mov     r2, rINST, lsr #8           @ r2<- A+
8017    beq     common_exceptionThrown      @ yes, handle the exception
8018    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8019    and     r2, r2, #15                 @ r2<- A
8020    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8021    SET_VREG(r0, r2)                    @ vA<- r0
8022    GOTO_OPCODE(ip)                     @ jump to next instruction
8023
8024/* continuation for OP_FILLED_NEW_ARRAY */
8025
8026    /*
8027     * On entry:
8028     *  r0 holds array class
8029     *  r10 holds AA or BA
8030     */
8031.LOP_FILLED_NEW_ARRAY_continue:
8032    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8033    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8034    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8035    .if     0
8036    mov     r1, r10                     @ r1<- AA (length)
8037    .else
8038    mov     r1, r10, lsr #4             @ r1<- B (length)
8039    .endif
8040    cmp     r3, #'I'                    @ array of ints?
8041    cmpne   r3, #'L'                    @ array of objects?
8042    cmpne   r3, #'['                    @ array of arrays?
8043    mov     r9, r1                      @ save length in r9
8044    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8045    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8046    cmp     r0, #0                      @ null return?
8047    beq     common_exceptionThrown      @ alloc failed, handle exception
8048
8049    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8050    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8051    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8052    subs    r9, r9, #1                  @ length--, check for neg
8053    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8054    bmi     2f                          @ was zero, bail
8055
8056    @ copy values from registers into the array
8057    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8058    .if     0
8059    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80601:  ldr     r3, [r2], #4                @ r3<- *r2++
8061    subs    r9, r9, #1                  @ count--
8062    str     r3, [r0], #4                @ *contents++ = vX
8063    bpl     1b
8064    @ continue at 2
8065    .else
8066    cmp     r9, #4                      @ length was initially 5?
8067    and     r2, r10, #15                @ r2<- A
8068    bne     1f                          @ <= 4 args, branch
8069    GET_VREG(r3, r2)                    @ r3<- vA
8070    sub     r9, r9, #1                  @ count--
8071    str     r3, [r0, #16]               @ contents[4] = vA
80721:  and     r2, r1, #15                 @ r2<- F/E/D/C
8073    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8074    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8075    subs    r9, r9, #1                  @ count--
8076    str     r3, [r0], #4                @ *contents++ = vX
8077    bpl     1b
8078    @ continue at 2
8079    .endif
8080
80812:
8082    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8083    GOTO_OPCODE(ip)                     @ execute it
8084
8085    /*
8086     * Throw an exception indicating that we have not implemented this
8087     * mode of filled-new-array.
8088     */
8089.LOP_FILLED_NEW_ARRAY_notimpl:
8090    ldr     r0, .L_strInternalError
8091    ldr     r1, .L_strFilledNewArrayNotImpl
8092    bl      dvmThrowException
8093    b       common_exceptionThrown
8094
8095    .if     (!0)                 @ define in one or the other, not both
8096.L_strFilledNewArrayNotImpl:
8097    .word   .LstrFilledNewArrayNotImpl
8098.L_strInternalError:
8099    .word   .LstrInternalError
8100    .endif
8101
8102/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8103
8104    /*
8105     * On entry:
8106     *  r0 holds array class
8107     *  r10 holds AA or BA
8108     */
8109.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8110    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8111    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8112    ldrb    r3, [r3, #1]                @ r3<- descriptor[1]
8113    .if     1
8114    mov     r1, r10                     @ r1<- AA (length)
8115    .else
8116    mov     r1, r10, lsr #4             @ r1<- B (length)
8117    .endif
8118    cmp     r3, #'I'                    @ array of ints?
8119    cmpne   r3, #'L'                    @ array of objects?
8120    cmpne   r3, #'['                    @ array of arrays?
8121    mov     r9, r1                      @ save length in r9
8122    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8123    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8124    cmp     r0, #0                      @ null return?
8125    beq     common_exceptionThrown      @ alloc failed, handle exception
8126
8127    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8128    str     r0, [rGLUE, #offGlue_retval]    @ retval.l <- new array
8129    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8130    subs    r9, r9, #1                  @ length--, check for neg
8131    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8132    bmi     2f                          @ was zero, bail
8133
8134    @ copy values from registers into the array
8135    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8136    .if     1
8137    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81381:  ldr     r3, [r2], #4                @ r3<- *r2++
8139    subs    r9, r9, #1                  @ count--
8140    str     r3, [r0], #4                @ *contents++ = vX
8141    bpl     1b
8142    @ continue at 2
8143    .else
8144    cmp     r9, #4                      @ length was initially 5?
8145    and     r2, r10, #15                @ r2<- A
8146    bne     1f                          @ <= 4 args, branch
8147    GET_VREG(r3, r2)                    @ r3<- vA
8148    sub     r9, r9, #1                  @ count--
8149    str     r3, [r0, #16]               @ contents[4] = vA
81501:  and     r2, r1, #15                 @ r2<- F/E/D/C
8151    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8152    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8153    subs    r9, r9, #1                  @ count--
8154    str     r3, [r0], #4                @ *contents++ = vX
8155    bpl     1b
8156    @ continue at 2
8157    .endif
8158
81592:
8160    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
8161    GOTO_OPCODE(ip)                     @ execute it
8162
8163    /*
8164     * Throw an exception indicating that we have not implemented this
8165     * mode of filled-new-array.
8166     */
8167.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8168    ldr     r0, .L_strInternalError
8169    ldr     r1, .L_strFilledNewArrayNotImpl
8170    bl      dvmThrowException
8171    b       common_exceptionThrown
8172
8173    .if     (!1)                 @ define in one or the other, not both
8174.L_strFilledNewArrayNotImpl:
8175    .word   .LstrFilledNewArrayNotImpl
8176.L_strInternalError:
8177    .word   .LstrInternalError
8178    .endif
8179
8180/* continuation for OP_CMPL_FLOAT */
8181.LOP_CMPL_FLOAT_finish:
8182    SET_VREG(r0, r9)                    @ vAA<- r0
8183    GOTO_OPCODE(ip)                     @ jump to next instruction
8184
8185/* continuation for OP_CMPG_FLOAT */
8186.LOP_CMPG_FLOAT_finish:
8187    SET_VREG(r0, r9)                    @ vAA<- r0
8188    GOTO_OPCODE(ip)                     @ jump to next instruction
8189
8190/* continuation for OP_CMPL_DOUBLE */
8191.LOP_CMPL_DOUBLE_finish:
8192    SET_VREG(r0, r9)                    @ vAA<- r0
8193    GOTO_OPCODE(ip)                     @ jump to next instruction
8194
8195/* continuation for OP_CMPG_DOUBLE */
8196.LOP_CMPG_DOUBLE_finish:
8197    SET_VREG(r0, r9)                    @ vAA<- r0
8198    GOTO_OPCODE(ip)                     @ jump to next instruction
8199
8200/* continuation for OP_CMP_LONG */
8201
8202.LOP_CMP_LONG_less:
8203    mvn     r1, #0                      @ r1<- -1
8204    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8205    @ instead, we just replicate the tail end.
8206    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8207    SET_VREG(r1, r9)                    @ vAA<- r1
8208    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8209    GOTO_OPCODE(ip)                     @ jump to next instruction
8210
8211.LOP_CMP_LONG_greater:
8212    mov     r1, #1                      @ r1<- 1
8213    @ fall through to _finish
8214
8215.LOP_CMP_LONG_finish:
8216    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8217    SET_VREG(r1, r9)                    @ vAA<- r1
8218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8219    GOTO_OPCODE(ip)                     @ jump to next instruction
8220
8221/* continuation for OP_AGET_WIDE */
8222
8223.LOP_AGET_WIDE_finish:
8224    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8225    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8226    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8227    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8228    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8229    GOTO_OPCODE(ip)                     @ jump to next instruction
8230
8231/* continuation for OP_APUT_WIDE */
8232
8233.LOP_APUT_WIDE_finish:
8234    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8235    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8237    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8238    GOTO_OPCODE(ip)                     @ jump to next instruction
8239
8240/* continuation for OP_APUT_OBJECT */
8241    /*
8242     * On entry:
8243     *  r1 = vBB (arrayObj)
8244     *  r9 = vAA (obj)
8245     *  r10 = offset into array (vBB + vCC * width)
8246     */
8247.LOP_APUT_OBJECT_finish:
8248    cmp     r9, #0                      @ storing null reference?
8249    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8250    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8251    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8252    bl      dvmCanPutArrayElement       @ test object type vs. array type
8253    cmp     r0, #0                      @ okay?
8254    beq     common_errArrayStore        @ no
8255.LOP_APUT_OBJECT_skip_check:
8256    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8258    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8259    GOTO_OPCODE(ip)                     @ jump to next instruction
8260
8261/* continuation for OP_IGET */
8262
8263    /*
8264     * Currently:
8265     *  r0 holds resolved field
8266     *  r9 holds object
8267     */
8268.LOP_IGET_finish:
8269    @bl      common_squeak0
8270    cmp     r9, #0                      @ check object for null
8271    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8272    beq     common_errNullObject        @ object was null
8273    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8274    SMP_DMB 0                   @ acquiring load
8275    mov     r2, rINST, lsr #8           @ r2<- A+
8276    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8277    and     r2, r2, #15                 @ r2<- A
8278    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8279    SET_VREG(r0, r2)                    @ fp[A]<- r0
8280    GOTO_OPCODE(ip)                     @ jump to next instruction
8281
8282/* continuation for OP_IGET_WIDE */
8283
8284    /*
8285     * Currently:
8286     *  r0 holds resolved field
8287     *  r9 holds object
8288     */
8289.LOP_IGET_WIDE_finish:
8290    cmp     r9, #0                      @ check object for null
8291    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8292    beq     common_errNullObject        @ object was null
8293    .if     0
8294    add     r0, r9, r3                  @ r0<- address of field
8295    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8296    .else
8297    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8298    .endif
8299    mov     r2, rINST, lsr #8           @ r2<- A+
8300    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8301    and     r2, r2, #15                 @ r2<- A
8302    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8303    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8304    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8305    GOTO_OPCODE(ip)                     @ jump to next instruction
8306
8307/* continuation for OP_IGET_OBJECT */
8308
8309    /*
8310     * Currently:
8311     *  r0 holds resolved field
8312     *  r9 holds object
8313     */
8314.LOP_IGET_OBJECT_finish:
8315    @bl      common_squeak0
8316    cmp     r9, #0                      @ check object for null
8317    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8318    beq     common_errNullObject        @ object was null
8319    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8320    SMP_DMB 0                   @ acquiring load
8321    mov     r2, rINST, lsr #8           @ r2<- A+
8322    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8323    and     r2, r2, #15                 @ r2<- A
8324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8325    SET_VREG(r0, r2)                    @ fp[A]<- r0
8326    GOTO_OPCODE(ip)                     @ jump to next instruction
8327
8328/* continuation for OP_IGET_BOOLEAN */
8329
8330    /*
8331     * Currently:
8332     *  r0 holds resolved field
8333     *  r9 holds object
8334     */
8335.LOP_IGET_BOOLEAN_finish:
8336    @bl      common_squeak1
8337    cmp     r9, #0                      @ check object for null
8338    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8339    beq     common_errNullObject        @ object was null
8340    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8341    SMP_DMB 0                   @ acquiring load
8342    mov     r2, rINST, lsr #8           @ r2<- A+
8343    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8344    and     r2, r2, #15                 @ r2<- A
8345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8346    SET_VREG(r0, r2)                    @ fp[A]<- r0
8347    GOTO_OPCODE(ip)                     @ jump to next instruction
8348
8349/* continuation for OP_IGET_BYTE */
8350
8351    /*
8352     * Currently:
8353     *  r0 holds resolved field
8354     *  r9 holds object
8355     */
8356.LOP_IGET_BYTE_finish:
8357    @bl      common_squeak2
8358    cmp     r9, #0                      @ check object for null
8359    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8360    beq     common_errNullObject        @ object was null
8361    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8362    SMP_DMB 0                   @ acquiring load
8363    mov     r2, rINST, lsr #8           @ r2<- A+
8364    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8365    and     r2, r2, #15                 @ r2<- A
8366    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8367    SET_VREG(r0, r2)                    @ fp[A]<- r0
8368    GOTO_OPCODE(ip)                     @ jump to next instruction
8369
8370/* continuation for OP_IGET_CHAR */
8371
8372    /*
8373     * Currently:
8374     *  r0 holds resolved field
8375     *  r9 holds object
8376     */
8377.LOP_IGET_CHAR_finish:
8378    @bl      common_squeak3
8379    cmp     r9, #0                      @ check object for null
8380    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8381    beq     common_errNullObject        @ object was null
8382    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8383    SMP_DMB 0                   @ acquiring load
8384    mov     r2, rINST, lsr #8           @ r2<- A+
8385    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8386    and     r2, r2, #15                 @ r2<- A
8387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8388    SET_VREG(r0, r2)                    @ fp[A]<- r0
8389    GOTO_OPCODE(ip)                     @ jump to next instruction
8390
8391/* continuation for OP_IGET_SHORT */
8392
8393    /*
8394     * Currently:
8395     *  r0 holds resolved field
8396     *  r9 holds object
8397     */
8398.LOP_IGET_SHORT_finish:
8399    @bl      common_squeak4
8400    cmp     r9, #0                      @ check object for null
8401    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8402    beq     common_errNullObject        @ object was null
8403    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8404    SMP_DMB 0                   @ acquiring load
8405    mov     r2, rINST, lsr #8           @ r2<- A+
8406    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8407    and     r2, r2, #15                 @ r2<- A
8408    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8409    SET_VREG(r0, r2)                    @ fp[A]<- r0
8410    GOTO_OPCODE(ip)                     @ jump to next instruction
8411
8412/* continuation for OP_IPUT */
8413
8414    /*
8415     * Currently:
8416     *  r0 holds resolved field
8417     *  r9 holds object
8418     */
8419.LOP_IPUT_finish:
8420    @bl      common_squeak0
8421    mov     r1, rINST, lsr #8           @ r1<- A+
8422    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8423    and     r1, r1, #15                 @ r1<- A
8424    cmp     r9, #0                      @ check object for null
8425    GET_VREG(r0, r1)                    @ r0<- fp[A]
8426    beq     common_errNullObject        @ object was null
8427    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8428    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8429    SMP_DMB 0                   @ releasing store
8430    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8431    GOTO_OPCODE(ip)                     @ jump to next instruction
8432
8433/* continuation for OP_IPUT_WIDE */
8434
8435    /*
8436     * Currently:
8437     *  r0 holds resolved field
8438     *  r9 holds object
8439     */
8440.LOP_IPUT_WIDE_finish:
8441    mov     r2, rINST, lsr #8           @ r2<- A+
8442    cmp     r9, #0                      @ check object for null
8443    and     r2, r2, #15                 @ r2<- A
8444    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8445    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8446    beq     common_errNullObject        @ object was null
8447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8448    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8449    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8450    .if     0
8451    add     r2, r9, r3                  @ r2<- target address
8452    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8453    .else
8454    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8455    .endif
8456    GOTO_OPCODE(r10)                    @ jump to next instruction
8457
8458/* continuation for OP_IPUT_OBJECT */
8459
8460    /*
8461     * Currently:
8462     *  r0 holds resolved field
8463     *  r9 holds object
8464     */
8465.LOP_IPUT_OBJECT_finish:
8466    @bl      common_squeak0
8467    mov     r1, rINST, lsr #8           @ r1<- A+
8468    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8469    and     r1, r1, #15                 @ r1<- A
8470    cmp     r9, #0                      @ check object for null
8471    GET_VREG(r0, r1)                    @ r0<- fp[A]
8472    beq     common_errNullObject        @ object was null
8473    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8475    SMP_DMB 0                   @ releasing store
8476    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8477    GOTO_OPCODE(ip)                     @ jump to next instruction
8478
8479/* continuation for OP_IPUT_BOOLEAN */
8480
8481    /*
8482     * Currently:
8483     *  r0 holds resolved field
8484     *  r9 holds object
8485     */
8486.LOP_IPUT_BOOLEAN_finish:
8487    @bl      common_squeak1
8488    mov     r1, rINST, lsr #8           @ r1<- A+
8489    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8490    and     r1, r1, #15                 @ r1<- A
8491    cmp     r9, #0                      @ check object for null
8492    GET_VREG(r0, r1)                    @ r0<- fp[A]
8493    beq     common_errNullObject        @ object was null
8494    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8496    SMP_DMB 0                   @ releasing store
8497    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8498    GOTO_OPCODE(ip)                     @ jump to next instruction
8499
8500/* continuation for OP_IPUT_BYTE */
8501
8502    /*
8503     * Currently:
8504     *  r0 holds resolved field
8505     *  r9 holds object
8506     */
8507.LOP_IPUT_BYTE_finish:
8508    @bl      common_squeak2
8509    mov     r1, rINST, lsr #8           @ r1<- A+
8510    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8511    and     r1, r1, #15                 @ r1<- A
8512    cmp     r9, #0                      @ check object for null
8513    GET_VREG(r0, r1)                    @ r0<- fp[A]
8514    beq     common_errNullObject        @ object was null
8515    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8516    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8517    SMP_DMB 0                   @ releasing store
8518    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8519    GOTO_OPCODE(ip)                     @ jump to next instruction
8520
8521/* continuation for OP_IPUT_CHAR */
8522
8523    /*
8524     * Currently:
8525     *  r0 holds resolved field
8526     *  r9 holds object
8527     */
8528.LOP_IPUT_CHAR_finish:
8529    @bl      common_squeak3
8530    mov     r1, rINST, lsr #8           @ r1<- A+
8531    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8532    and     r1, r1, #15                 @ r1<- A
8533    cmp     r9, #0                      @ check object for null
8534    GET_VREG(r0, r1)                    @ r0<- fp[A]
8535    beq     common_errNullObject        @ object was null
8536    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8537    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8538    SMP_DMB 0                   @ releasing store
8539    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8540    GOTO_OPCODE(ip)                     @ jump to next instruction
8541
8542/* continuation for OP_IPUT_SHORT */
8543
8544    /*
8545     * Currently:
8546     *  r0 holds resolved field
8547     *  r9 holds object
8548     */
8549.LOP_IPUT_SHORT_finish:
8550    @bl      common_squeak4
8551    mov     r1, rINST, lsr #8           @ r1<- A+
8552    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8553    and     r1, r1, #15                 @ r1<- A
8554    cmp     r9, #0                      @ check object for null
8555    GET_VREG(r0, r1)                    @ r0<- fp[A]
8556    beq     common_errNullObject        @ object was null
8557    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8559    SMP_DMB 0                   @ releasing store
8560    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8561    GOTO_OPCODE(ip)                     @ jump to next instruction
8562
8563/* continuation for OP_SGET */
8564
8565    /*
8566     * Continuation if the field has not yet been resolved.
8567     *  r1: BBBB field ref
8568     */
8569.LOP_SGET_resolve:
8570    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8571    EXPORT_PC()                         @ resolve() could throw, so export now
8572    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8573    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8574    cmp     r0, #0                      @ success?
8575    bne     .LOP_SGET_finish          @ yes, finish
8576    b       common_exceptionThrown      @ no, handle exception
8577
8578/* continuation for OP_SGET_WIDE */
8579
8580    /*
8581     * Continuation if the field has not yet been resolved.
8582     *  r1: BBBB field ref
8583     *
8584     * Returns StaticField pointer in r0.
8585     */
8586.LOP_SGET_WIDE_resolve:
8587    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8588    EXPORT_PC()                         @ resolve() could throw, so export now
8589    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8590    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8591    cmp     r0, #0                      @ success?
8592    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8593    b       common_exceptionThrown      @ no, handle exception
8594
8595/* continuation for OP_SGET_OBJECT */
8596
8597    /*
8598     * Continuation if the field has not yet been resolved.
8599     *  r1: BBBB field ref
8600     */
8601.LOP_SGET_OBJECT_resolve:
8602    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8603    EXPORT_PC()                         @ resolve() could throw, so export now
8604    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8605    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8606    cmp     r0, #0                      @ success?
8607    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8608    b       common_exceptionThrown      @ no, handle exception
8609
8610/* continuation for OP_SGET_BOOLEAN */
8611
8612    /*
8613     * Continuation if the field has not yet been resolved.
8614     *  r1: BBBB field ref
8615     */
8616.LOP_SGET_BOOLEAN_resolve:
8617    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8618    EXPORT_PC()                         @ resolve() could throw, so export now
8619    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8620    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8621    cmp     r0, #0                      @ success?
8622    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8623    b       common_exceptionThrown      @ no, handle exception
8624
8625/* continuation for OP_SGET_BYTE */
8626
8627    /*
8628     * Continuation if the field has not yet been resolved.
8629     *  r1: BBBB field ref
8630     */
8631.LOP_SGET_BYTE_resolve:
8632    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8633    EXPORT_PC()                         @ resolve() could throw, so export now
8634    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8635    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8636    cmp     r0, #0                      @ success?
8637    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8638    b       common_exceptionThrown      @ no, handle exception
8639
8640/* continuation for OP_SGET_CHAR */
8641
8642    /*
8643     * Continuation if the field has not yet been resolved.
8644     *  r1: BBBB field ref
8645     */
8646.LOP_SGET_CHAR_resolve:
8647    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8648    EXPORT_PC()                         @ resolve() could throw, so export now
8649    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8650    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8651    cmp     r0, #0                      @ success?
8652    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8653    b       common_exceptionThrown      @ no, handle exception
8654
8655/* continuation for OP_SGET_SHORT */
8656
8657    /*
8658     * Continuation if the field has not yet been resolved.
8659     *  r1: BBBB field ref
8660     */
8661.LOP_SGET_SHORT_resolve:
8662    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8663    EXPORT_PC()                         @ resolve() could throw, so export now
8664    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8665    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8666    cmp     r0, #0                      @ success?
8667    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8668    b       common_exceptionThrown      @ no, handle exception
8669
8670/* continuation for OP_SPUT */
8671
8672    /*
8673     * Continuation if the field has not yet been resolved.
8674     *  r1: BBBB field ref
8675     */
8676.LOP_SPUT_resolve:
8677    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8678    EXPORT_PC()                         @ resolve() could throw, so export now
8679    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8680    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8681    cmp     r0, #0                      @ success?
8682    bne     .LOP_SPUT_finish          @ yes, finish
8683    b       common_exceptionThrown      @ no, handle exception
8684
8685/* continuation for OP_SPUT_WIDE */
8686
8687    /*
8688     * Continuation if the field has not yet been resolved.
8689     *  r1: BBBB field ref
8690     *  r9: &fp[AA]
8691     *
8692     * Returns StaticField pointer in r2.
8693     */
8694.LOP_SPUT_WIDE_resolve:
8695    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8696    EXPORT_PC()                         @ resolve() could throw, so export now
8697    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8698    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8699    cmp     r0, #0                      @ success?
8700    mov     r2, r0                      @ copy to r2
8701    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8702    b       common_exceptionThrown      @ no, handle exception
8703
8704/* continuation for OP_SPUT_OBJECT */
8705
8706    /*
8707     * Continuation if the field has not yet been resolved.
8708     *  r1: BBBB field ref
8709     */
8710.LOP_SPUT_OBJECT_resolve:
8711    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8712    EXPORT_PC()                         @ resolve() could throw, so export now
8713    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8714    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8715    cmp     r0, #0                      @ success?
8716    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
8717    b       common_exceptionThrown      @ no, handle exception
8718
8719/* continuation for OP_SPUT_BOOLEAN */
8720
8721    /*
8722     * Continuation if the field has not yet been resolved.
8723     *  r1: BBBB field ref
8724     */
8725.LOP_SPUT_BOOLEAN_resolve:
8726    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8727    EXPORT_PC()                         @ resolve() could throw, so export now
8728    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8729    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8730    cmp     r0, #0                      @ success?
8731    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8732    b       common_exceptionThrown      @ no, handle exception
8733
8734/* continuation for OP_SPUT_BYTE */
8735
8736    /*
8737     * Continuation if the field has not yet been resolved.
8738     *  r1: BBBB field ref
8739     */
8740.LOP_SPUT_BYTE_resolve:
8741    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8742    EXPORT_PC()                         @ resolve() could throw, so export now
8743    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8744    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8745    cmp     r0, #0                      @ success?
8746    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8747    b       common_exceptionThrown      @ no, handle exception
8748
8749/* continuation for OP_SPUT_CHAR */
8750
8751    /*
8752     * Continuation if the field has not yet been resolved.
8753     *  r1: BBBB field ref
8754     */
8755.LOP_SPUT_CHAR_resolve:
8756    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8757    EXPORT_PC()                         @ resolve() could throw, so export now
8758    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8759    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8760    cmp     r0, #0                      @ success?
8761    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8762    b       common_exceptionThrown      @ no, handle exception
8763
8764/* continuation for OP_SPUT_SHORT */
8765
8766    /*
8767     * Continuation if the field has not yet been resolved.
8768     *  r1: BBBB field ref
8769     */
8770.LOP_SPUT_SHORT_resolve:
8771    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8772    EXPORT_PC()                         @ resolve() could throw, so export now
8773    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8774    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8775    cmp     r0, #0                      @ success?
8776    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8777    b       common_exceptionThrown      @ no, handle exception
8778
8779/* continuation for OP_INVOKE_VIRTUAL */
8780
8781    /*
8782     * At this point:
8783     *  r0 = resolved base method
8784     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8785     */
8786.LOP_INVOKE_VIRTUAL_continue:
8787    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8788    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8789    cmp     r1, #0                      @ is "this" null?
8790    beq     common_errNullObject        @ null "this", throw exception
8791    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8792    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8793    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8794    bl      common_invokeMethodNoRange @ continue on
8795
8796/* continuation for OP_INVOKE_SUPER */
8797
8798    /*
8799     * At this point:
8800     *  r0 = resolved base method
8801     *  r9 = method->clazz
8802     */
8803.LOP_INVOKE_SUPER_continue:
8804    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8805    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8806    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8807    EXPORT_PC()                         @ must export for invoke
8808    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8809    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8810    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8811    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8812    bl      common_invokeMethodNoRange @ continue on
8813
8814.LOP_INVOKE_SUPER_resolve:
8815    mov     r0, r9                      @ r0<- method->clazz
8816    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8817    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8818    cmp     r0, #0                      @ got null?
8819    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8820    b       common_exceptionThrown      @ yes, handle exception
8821
8822    /*
8823     * Throw a NoSuchMethodError with the method name as the message.
8824     *  r0 = resolved base method
8825     */
8826.LOP_INVOKE_SUPER_nsm:
8827    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8828    b       common_errNoSuchMethod
8829
8830/* continuation for OP_INVOKE_DIRECT */
8831
8832    /*
8833     * On entry:
8834     *  r1 = reference (BBBB or CCCC)
8835     *  r10 = "this" register
8836     */
8837.LOP_INVOKE_DIRECT_resolve:
8838    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8839    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8840    mov     r2, #METHOD_DIRECT          @ resolver method type
8841    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8842    cmp     r0, #0                      @ got null?
8843    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8844    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8845    b       common_exceptionThrown      @ yes, handle exception
8846
8847/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8848
8849    /*
8850     * At this point:
8851     *  r0 = resolved base method
8852     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8853     */
8854.LOP_INVOKE_VIRTUAL_RANGE_continue:
8855    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8856    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8857    cmp     r1, #0                      @ is "this" null?
8858    beq     common_errNullObject        @ null "this", throw exception
8859    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8860    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8861    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8862    bl      common_invokeMethodRange @ continue on
8863
8864/* continuation for OP_INVOKE_SUPER_RANGE */
8865
8866    /*
8867     * At this point:
8868     *  r0 = resolved base method
8869     *  r9 = method->clazz
8870     */
8871.LOP_INVOKE_SUPER_RANGE_continue:
8872    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8873    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8874    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8875    EXPORT_PC()                         @ must export for invoke
8876    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8877    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8878    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8879    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8880    bl      common_invokeMethodRange @ continue on
8881
8882.LOP_INVOKE_SUPER_RANGE_resolve:
8883    mov     r0, r9                      @ r0<- method->clazz
8884    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8885    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8886    cmp     r0, #0                      @ got null?
8887    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8888    b       common_exceptionThrown      @ yes, handle exception
8889
8890    /*
8891     * Throw a NoSuchMethodError with the method name as the message.
8892     *  r0 = resolved base method
8893     */
8894.LOP_INVOKE_SUPER_RANGE_nsm:
8895    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8896    b       common_errNoSuchMethod
8897
8898/* continuation for OP_INVOKE_DIRECT_RANGE */
8899
8900    /*
8901     * On entry:
8902     *  r1 = reference (BBBB or CCCC)
8903     *  r10 = "this" register
8904     */
8905.LOP_INVOKE_DIRECT_RANGE_resolve:
8906    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8907    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8908    mov     r2, #METHOD_DIRECT          @ resolver method type
8909    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8910    cmp     r0, #0                      @ got null?
8911    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8912    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8913    b       common_exceptionThrown      @ yes, handle exception
8914
8915/* continuation for OP_FLOAT_TO_LONG */
8916/*
8917 * Convert the float in r0 to a long in r0/r1.
8918 *
8919 * We have to clip values to long min/max per the specification.  The
8920 * expected common case is a "reasonable" value that converts directly
8921 * to modest integer.  The EABI convert function isn't doing this for us.
8922 */
8923f2l_doconv:
8924    stmfd   sp!, {r4, lr}
8925    mov     r1, #0x5f000000             @ (float)maxlong
8926    mov     r4, r0
8927    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8928    cmp     r0, #0                      @ nonzero == yes
8929    mvnne   r0, #0                      @ return maxlong (7fffffff)
8930    mvnne   r1, #0x80000000
8931    ldmnefd sp!, {r4, pc}
8932
8933    mov     r0, r4                      @ recover arg
8934    mov     r1, #0xdf000000             @ (float)minlong
8935    bl      __aeabi_fcmple              @ is arg <= minlong?
8936    cmp     r0, #0                      @ nonzero == yes
8937    movne   r0, #0                      @ return minlong (80000000)
8938    movne   r1, #0x80000000
8939    ldmnefd sp!, {r4, pc}
8940
8941    mov     r0, r4                      @ recover arg
8942    mov     r1, r4
8943    bl      __aeabi_fcmpeq              @ is arg == self?
8944    cmp     r0, #0                      @ zero == no
8945    moveq   r1, #0                      @ return zero for NaN
8946    ldmeqfd sp!, {r4, pc}
8947
8948    mov     r0, r4                      @ recover arg
8949    bl      __aeabi_f2lz                @ convert float to long
8950    ldmfd   sp!, {r4, pc}
8951
8952/* continuation for OP_DOUBLE_TO_LONG */
8953/*
8954 * Convert the double in r0/r1 to a long in r0/r1.
8955 *
8956 * We have to clip values to long min/max per the specification.  The
8957 * expected common case is a "reasonable" value that converts directly
8958 * to modest integer.  The EABI convert function isn't doing this for us.
8959 */
8960d2l_doconv:
8961    stmfd   sp!, {r4, r5, lr}           @ save regs
8962    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8963    add     r3, #0x00e00000             @  0x43e00000
8964    mov     r2, #0                      @ maxlong, as a double (low word)
8965    sub     sp, sp, #4                  @ align for EABI
8966    mov     r4, r0                      @ save a copy of r0
8967    mov     r5, r1                      @  and r1
8968    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8969    cmp     r0, #0                      @ nonzero == yes
8970    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
8971    mvnne   r1, #0x80000000
8972    bne     1f
8973
8974    mov     r0, r4                      @ recover arg
8975    mov     r1, r5
8976    mov     r3, #0xc3000000             @ minlong, as a double (high word)
8977    add     r3, #0x00e00000             @  0xc3e00000
8978    mov     r2, #0                      @ minlong, as a double (low word)
8979    bl      __aeabi_dcmple              @ is arg <= minlong?
8980    cmp     r0, #0                      @ nonzero == yes
8981    movne   r0, #0                      @ return minlong (8000000000000000)
8982    movne   r1, #0x80000000
8983    bne     1f
8984
8985    mov     r0, r4                      @ recover arg
8986    mov     r1, r5
8987    mov     r2, r4                      @ compare against self
8988    mov     r3, r5
8989    bl      __aeabi_dcmpeq              @ is arg == self?
8990    cmp     r0, #0                      @ zero == no
8991    moveq   r1, #0                      @ return zero for NaN
8992    beq     1f
8993
8994    mov     r0, r4                      @ recover arg
8995    mov     r1, r5
8996    bl      __aeabi_d2lz                @ convert double to long
8997
89981:
8999    add     sp, sp, #4
9000    ldmfd   sp!, {r4, r5, pc}
9001
9002/* continuation for OP_MUL_LONG */
9003
9004.LOP_MUL_LONG_finish:
9005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9006    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9007    GOTO_OPCODE(ip)                     @ jump to next instruction
9008
9009/* continuation for OP_SHL_LONG */
9010
9011.LOP_SHL_LONG_finish:
9012    mov     r0, r0, asl r2              @  r0<- r0 << r2
9013    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9014    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9015    GOTO_OPCODE(ip)                     @ jump to next instruction
9016
9017/* continuation for OP_SHR_LONG */
9018
9019.LOP_SHR_LONG_finish:
9020    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9021    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9022    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9023    GOTO_OPCODE(ip)                     @ jump to next instruction
9024
9025/* continuation for OP_USHR_LONG */
9026
9027.LOP_USHR_LONG_finish:
9028    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9030    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9031    GOTO_OPCODE(ip)                     @ jump to next instruction
9032
9033/* continuation for OP_SHL_LONG_2ADDR */
9034
9035.LOP_SHL_LONG_2ADDR_finish:
9036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9037    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9038    GOTO_OPCODE(ip)                     @ jump to next instruction
9039
9040/* continuation for OP_SHR_LONG_2ADDR */
9041
9042.LOP_SHR_LONG_2ADDR_finish:
9043    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9044    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9045    GOTO_OPCODE(ip)                     @ jump to next instruction
9046
9047/* continuation for OP_USHR_LONG_2ADDR */
9048
9049.LOP_USHR_LONG_2ADDR_finish:
9050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9051    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9052    GOTO_OPCODE(ip)                     @ jump to next instruction
9053
9054/* continuation for OP_IGET_VOLATILE */
9055
9056    /*
9057     * Currently:
9058     *  r0 holds resolved field
9059     *  r9 holds object
9060     */
9061.LOP_IGET_VOLATILE_finish:
9062    @bl      common_squeak0
9063    cmp     r9, #0                      @ check object for null
9064    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9065    beq     common_errNullObject        @ object was null
9066    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9067    SMP_DMB 1                   @ acquiring load
9068    mov     r2, rINST, lsr #8           @ r2<- A+
9069    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9070    and     r2, r2, #15                 @ r2<- A
9071    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9072    SET_VREG(r0, r2)                    @ fp[A]<- r0
9073    GOTO_OPCODE(ip)                     @ jump to next instruction
9074
9075/* continuation for OP_IPUT_VOLATILE */
9076
9077    /*
9078     * Currently:
9079     *  r0 holds resolved field
9080     *  r9 holds object
9081     */
9082.LOP_IPUT_VOLATILE_finish:
9083    @bl      common_squeak0
9084    mov     r1, rINST, lsr #8           @ r1<- A+
9085    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9086    and     r1, r1, #15                 @ r1<- A
9087    cmp     r9, #0                      @ check object for null
9088    GET_VREG(r0, r1)                    @ r0<- fp[A]
9089    beq     common_errNullObject        @ object was null
9090    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9091    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9092    SMP_DMB 1                   @ releasing store
9093    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9094    GOTO_OPCODE(ip)                     @ jump to next instruction
9095
9096/* continuation for OP_SGET_VOLATILE */
9097
9098    /*
9099     * Continuation if the field has not yet been resolved.
9100     *  r1: BBBB field ref
9101     */
9102.LOP_SGET_VOLATILE_resolve:
9103    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9104    EXPORT_PC()                         @ resolve() could throw, so export now
9105    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9106    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9107    cmp     r0, #0                      @ success?
9108    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9109    b       common_exceptionThrown      @ no, handle exception
9110
9111/* continuation for OP_SPUT_VOLATILE */
9112
9113    /*
9114     * Continuation if the field has not yet been resolved.
9115     *  r1: BBBB field ref
9116     */
9117.LOP_SPUT_VOLATILE_resolve:
9118    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9119    EXPORT_PC()                         @ resolve() could throw, so export now
9120    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9121    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9122    cmp     r0, #0                      @ success?
9123    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9124    b       common_exceptionThrown      @ no, handle exception
9125
9126/* continuation for OP_IGET_OBJECT_VOLATILE */
9127
9128    /*
9129     * Currently:
9130     *  r0 holds resolved field
9131     *  r9 holds object
9132     */
9133.LOP_IGET_OBJECT_VOLATILE_finish:
9134    @bl      common_squeak0
9135    cmp     r9, #0                      @ check object for null
9136    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9137    beq     common_errNullObject        @ object was null
9138    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9139    SMP_DMB 1                   @ acquiring load
9140    mov     r2, rINST, lsr #8           @ r2<- A+
9141    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9142    and     r2, r2, #15                 @ r2<- A
9143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9144    SET_VREG(r0, r2)                    @ fp[A]<- r0
9145    GOTO_OPCODE(ip)                     @ jump to next instruction
9146
9147/* continuation for OP_IGET_WIDE_VOLATILE */
9148
9149    /*
9150     * Currently:
9151     *  r0 holds resolved field
9152     *  r9 holds object
9153     */
9154.LOP_IGET_WIDE_VOLATILE_finish:
9155    cmp     r9, #0                      @ check object for null
9156    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9157    beq     common_errNullObject        @ object was null
9158    .if     1
9159    add     r0, r9, r3                  @ r0<- address of field
9160    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9161    .else
9162    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9163    .endif
9164    mov     r2, rINST, lsr #8           @ r2<- A+
9165    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9166    and     r2, r2, #15                 @ r2<- A
9167    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9168    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9169    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9170    GOTO_OPCODE(ip)                     @ jump to next instruction
9171
9172/* continuation for OP_IPUT_WIDE_VOLATILE */
9173
9174    /*
9175     * Currently:
9176     *  r0 holds resolved field
9177     *  r9 holds object
9178     */
9179.LOP_IPUT_WIDE_VOLATILE_finish:
9180    mov     r2, rINST, lsr #8           @ r2<- A+
9181    cmp     r9, #0                      @ check object for null
9182    and     r2, r2, #15                 @ r2<- A
9183    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9184    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9185    beq     common_errNullObject        @ object was null
9186    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9187    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9188    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9189    .if     1
9190    add     r2, r9, r3                  @ r2<- target address
9191    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9192    .else
9193    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9194    .endif
9195    GOTO_OPCODE(r10)                    @ jump to next instruction
9196
9197/* continuation for OP_SGET_WIDE_VOLATILE */
9198
9199    /*
9200     * Continuation if the field has not yet been resolved.
9201     *  r1: BBBB field ref
9202     *
9203     * Returns StaticField pointer in r0.
9204     */
9205.LOP_SGET_WIDE_VOLATILE_resolve:
9206    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9207    EXPORT_PC()                         @ resolve() could throw, so export now
9208    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9209    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9210    cmp     r0, #0                      @ success?
9211    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9212    b       common_exceptionThrown      @ no, handle exception
9213
9214/* continuation for OP_SPUT_WIDE_VOLATILE */
9215
9216    /*
9217     * Continuation if the field has not yet been resolved.
9218     *  r1: BBBB field ref
9219     *  r9: &fp[AA]
9220     *
9221     * Returns StaticField pointer in r2.
9222     */
9223.LOP_SPUT_WIDE_VOLATILE_resolve:
9224    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9225    EXPORT_PC()                         @ resolve() could throw, so export now
9226    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9227    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9228    cmp     r0, #0                      @ success?
9229    mov     r2, r0                      @ copy to r2
9230    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9231    b       common_exceptionThrown      @ no, handle exception
9232
9233/* continuation for OP_EXECUTE_INLINE */
9234
9235    /*
9236     * Extract args, call function.
9237     *  r0 = #of args (0-4)
9238     *  r10 = call index
9239     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9240     *
9241     * Other ideas:
9242     * - Use a jump table from the main piece to jump directly into the
9243     *   AND/LDR pairs.  Costs a data load, saves a branch.
9244     * - Have five separate pieces that do the loading, so we can work the
9245     *   interleave a little better.  Increases code size.
9246     */
9247.LOP_EXECUTE_INLINE_continue:
9248    rsb     r0, r0, #4                  @ r0<- 4-r0
9249    FETCH(r9, 2)                        @ r9<- FEDC
9250    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9251    bl      common_abort                @ (skipped due to ARM prefetch)
92524:  and     ip, r9, #0xf000             @ isolate F
9253    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92543:  and     ip, r9, #0x0f00             @ isolate E
9255    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92562:  and     ip, r9, #0x00f0             @ isolate D
9257    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92581:  and     ip, r9, #0x000f             @ isolate C
9259    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92600:
9261    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9262    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9263    @ (not reached)
9264
9265.LOP_EXECUTE_INLINE_table:
9266    .word   gDvmInlineOpsTable
9267
9268/* continuation for OP_EXECUTE_INLINE_RANGE */
9269
9270    /*
9271     * Extract args, call function.
9272     *  r0 = #of args (0-4)
9273     *  r10 = call index
9274     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9275     */
9276.LOP_EXECUTE_INLINE_RANGE_continue:
9277    rsb     r0, r0, #4                  @ r0<- 4-r0
9278    FETCH(r9, 2)                        @ r9<- CCCC
9279    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9280    bl      common_abort                @ (skipped due to ARM prefetch)
92814:  add     ip, r9, #3                  @ base+3
9282    GET_VREG(r3, ip)                    @ r3<- vBase[3]
92833:  add     ip, r9, #2                  @ base+2
9284    GET_VREG(r2, ip)                    @ r2<- vBase[2]
92852:  add     ip, r9, #1                  @ base+1
9286    GET_VREG(r1, ip)                    @ r1<- vBase[1]
92871:  add     ip, r9, #0                  @ (nop)
9288    GET_VREG(r0, ip)                    @ r0<- vBase[0]
92890:
9290    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9291    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9292    @ (not reached)
9293
9294.LOP_EXECUTE_INLINE_RANGE_table:
9295    .word   gDvmInlineOpsTable
9296
9297/* continuation for OP_IPUT_OBJECT_VOLATILE */
9298
9299    /*
9300     * Currently:
9301     *  r0 holds resolved field
9302     *  r9 holds object
9303     */
9304.LOP_IPUT_OBJECT_VOLATILE_finish:
9305    @bl      common_squeak0
9306    mov     r1, rINST, lsr #8           @ r1<- A+
9307    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9308    and     r1, r1, #15                 @ r1<- A
9309    cmp     r9, #0                      @ check object for null
9310    GET_VREG(r0, r1)                    @ r0<- fp[A]
9311    beq     common_errNullObject        @ object was null
9312    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9313    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9314    SMP_DMB 1                   @ releasing store
9315    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9316    GOTO_OPCODE(ip)                     @ jump to next instruction
9317
9318/* continuation for OP_SGET_OBJECT_VOLATILE */
9319
9320    /*
9321     * Continuation if the field has not yet been resolved.
9322     *  r1: BBBB field ref
9323     */
9324.LOP_SGET_OBJECT_VOLATILE_resolve:
9325    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9326    EXPORT_PC()                         @ resolve() could throw, so export now
9327    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9328    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9329    cmp     r0, #0                      @ success?
9330    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9331    b       common_exceptionThrown      @ no, handle exception
9332
9333/* continuation for OP_SPUT_OBJECT_VOLATILE */
9334
9335    /*
9336     * Continuation if the field has not yet been resolved.
9337     *  r1: BBBB field ref
9338     */
9339.LOP_SPUT_OBJECT_VOLATILE_resolve:
9340    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9341    EXPORT_PC()                         @ resolve() could throw, so export now
9342    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9343    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9344    cmp     r0, #0                      @ success?
9345    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
9346    b       common_exceptionThrown      @ no, handle exception
9347
9348    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9349    .global dvmAsmSisterEnd
9350dvmAsmSisterEnd:
9351
9352/* File: armv5te/footer.S */
9353
9354/*
9355 * ===========================================================================
9356 *  Common subroutines and data
9357 * ===========================================================================
9358 */
9359
9360
9361
9362    .text
9363    .align  2
9364
9365#if defined(WITH_JIT)
9366#if defined(WITH_SELF_VERIFICATION)
9367    .global dvmJitToInterpPunt
9368dvmJitToInterpPunt:
9369    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9370    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9371    mov    r3, #0
9372    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9373    b      jitSVShadowRunEnd            @ doesn't return
9374
9375    .global dvmJitToInterpSingleStep
9376dvmJitToInterpSingleStep:
9377    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9378    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9379    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9380    b      jitSVShadowRunEnd            @ doesn't return
9381
9382    .global dvmJitToInterpTraceSelectNoChain
9383dvmJitToInterpTraceSelectNoChain:
9384    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9385    mov    r0,rPC                       @ pass our target PC
9386    mov    r2,#kSVSTraceSelectNoChain   @ r2<- interpreter entry point
9387    mov    r3, #0
9388    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9389    b      jitSVShadowRunEnd            @ doesn't return
9390
9391    .global dvmJitToInterpTraceSelect
9392dvmJitToInterpTraceSelect:
9393    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9394    ldr    r0,[lr, #-1]                 @ pass our target PC
9395    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9396    mov    r3, #0
9397    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9398    b      jitSVShadowRunEnd            @ doesn't return
9399
9400    .global dvmJitToInterpBackwardBranch
9401dvmJitToInterpBackwardBranch:
9402    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9403    ldr    r0,[lr, #-1]                 @ pass our target PC
9404    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9405    mov    r3, #0
9406    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9407    b      jitSVShadowRunEnd            @ doesn't return
9408
9409    .global dvmJitToInterpNormal
9410dvmJitToInterpNormal:
9411    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9412    ldr    r0,[lr, #-1]                 @ pass our target PC
9413    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9414    mov    r3, #0
9415    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9416    b      jitSVShadowRunEnd            @ doesn't return
9417
9418    .global dvmJitToInterpNoChain
9419dvmJitToInterpNoChain:
9420    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9421    mov    r0,rPC                       @ pass our target PC
9422    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9423    mov    r3, #0
9424    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9425    b      jitSVShadowRunEnd            @ doesn't return
9426#else
9427/*
9428 * Return from the translation cache to the interpreter when the compiler is
9429 * having issues translating/executing a Dalvik instruction. We have to skip
9430 * the code cache lookup otherwise it is possible to indefinitely bouce
9431 * between the interpreter and the code cache if the instruction that fails
9432 * to be compiled happens to be at a trace start.
9433 */
9434    .global dvmJitToInterpPunt
9435dvmJitToInterpPunt:
9436    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9437    mov    rPC, r0
9438#if defined(WITH_JIT_TUNING)
9439    mov    r0,lr
9440    bl     dvmBumpPunt;
9441#endif
9442    EXPORT_PC()
9443    mov    r0, #0
9444    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9445    adrl   rIBASE, dvmAsmInstructionStart
9446    FETCH_INST()
9447    GET_INST_OPCODE(ip)
9448    GOTO_OPCODE(ip)
9449
9450/*
9451 * Return to the interpreter to handle a single instruction.
9452 * On entry:
9453 *    r0 <= PC
9454 *    r1 <= PC of resume instruction
9455 *    lr <= resume point in translation
9456 */
9457    .global dvmJitToInterpSingleStep
9458dvmJitToInterpSingleStep:
9459    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9460    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9461    mov    r1,#kInterpEntryInstr
9462    @ enum is 4 byte in aapcs-EABI
9463    str    r1, [rGLUE, #offGlue_entryPoint]
9464    mov    rPC,r0
9465    EXPORT_PC()
9466
9467    adrl   rIBASE, dvmAsmInstructionStart
9468    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9469    str    r2,[rGLUE,#offGlue_jitState]
9470    mov    r1,#1                  @ set changeInterp to bail to debug interp
9471    b      common_gotoBail
9472
9473/*
9474 * Return from the translation cache and immediately request
9475 * a translation for the exit target.  Commonly used for callees.
9476 */
9477    .global dvmJitToInterpTraceSelectNoChain
9478dvmJitToInterpTraceSelectNoChain:
9479#if defined(WITH_JIT_TUNING)
9480    bl     dvmBumpNoChain
9481#endif
9482    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9483    mov    r0,rPC
9484    bl     dvmJitGetCodeAddr        @ Is there a translation?
9485    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9486    mov    r1, rPC                  @ arg1 of translation may need this
9487    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9488    cmp    r0,#0
9489    bxne   r0                       @ continue native execution if so
9490    b      2f
9491
9492/*
9493 * Return from the translation cache and immediately request
9494 * a translation for the exit target.  Commonly used following
9495 * invokes.
9496 */
9497    .global dvmJitToInterpTraceSelect
9498dvmJitToInterpTraceSelect:
9499    ldr    rPC,[lr, #-1]           @ get our target PC
9500    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9501    add    rINST,lr,#-5            @ save start of chain branch
9502    add    rINST, #-4              @  .. which is 9 bytes back
9503    mov    r0,rPC
9504    bl     dvmJitGetCodeAddr       @ Is there a translation?
9505    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9506    cmp    r0,#0
9507    beq    2f
9508    mov    r1,rINST
9509    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9510    mov    r1, rPC                  @ arg1 of translation may need this
9511    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9512    cmp    r0,#0                    @ successful chain?
9513    bxne   r0                       @ continue native execution
9514    b      toInterpreter            @ didn't chain - resume with interpreter
9515
9516/* No translation, so request one if profiling isn't disabled*/
95172:
9518    adrl   rIBASE, dvmAsmInstructionStart
9519    GET_JIT_PROF_TABLE(r0)
9520    FETCH_INST()
9521    cmp    r0, #0
9522    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9523    bne    common_selectTrace
9524    GET_INST_OPCODE(ip)
9525    GOTO_OPCODE(ip)
9526
9527/*
9528 * Return from the translation cache to the interpreter.
9529 * The return was done with a BLX from thumb mode, and
9530 * the following 32-bit word contains the target rPC value.
9531 * Note that lr (r14) will have its low-order bit set to denote
9532 * its thumb-mode origin.
9533 *
9534 * We'll need to stash our lr origin away, recover the new
9535 * target and then check to see if there is a translation available
9536 * for our new target.  If so, we do a translation chain and
9537 * go back to native execution.  Otherwise, it's back to the
9538 * interpreter (after treating this entry as a potential
9539 * trace start).
9540 */
9541    .global dvmJitToInterpNormal
9542dvmJitToInterpNormal:
9543    ldr    rPC,[lr, #-1]           @ get our target PC
9544    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9545    add    rINST,lr,#-5            @ save start of chain branch
9546    add    rINST,#-4               @ .. which is 9 bytes back
9547#if defined(WITH_JIT_TUNING)
9548    bl     dvmBumpNormal
9549#endif
9550    mov    r0,rPC
9551    bl     dvmJitGetCodeAddr        @ Is there a translation?
9552    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9553    cmp    r0,#0
9554    beq    toInterpreter            @ go if not, otherwise do chain
9555    mov    r1,rINST
9556    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9557    mov    r1, rPC                  @ arg1 of translation may need this
9558    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9559    cmp    r0,#0                    @ successful chain?
9560    bxne   r0                       @ continue native execution
9561    b      toInterpreter            @ didn't chain - resume with interpreter
9562
9563/*
9564 * Return from the translation cache to the interpreter to do method invocation.
9565 * Check if translation exists for the callee, but don't chain to it.
9566 */
9567    .global dvmJitToInterpNoChain
9568dvmJitToInterpNoChain:
9569#if defined(WITH_JIT_TUNING)
9570    bl     dvmBumpNoChain
9571#endif
9572    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9573    mov    r0,rPC
9574    bl     dvmJitGetCodeAddr        @ Is there a translation?
9575    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9576    mov    r1, rPC                  @ arg1 of translation may need this
9577    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9578    cmp    r0,#0
9579    bxne   r0                       @ continue native execution if so
9580#endif
9581
9582/*
9583 * No translation, restore interpreter regs and start interpreting.
9584 * rGLUE & rFP were preserved in the translated code, and rPC has
9585 * already been restored by the time we get here.  We'll need to set
9586 * up rIBASE & rINST, and load the address of the JitTable into r0.
9587 */
9588toInterpreter:
9589    EXPORT_PC()
9590    adrl   rIBASE, dvmAsmInstructionStart
9591    FETCH_INST()
9592    GET_JIT_PROF_TABLE(r0)
9593    @ NOTE: intended fallthrough
9594/*
9595 * Common code to update potential trace start counter, and initiate
9596 * a trace-build if appropriate.  On entry, rPC should point to the
9597 * next instruction to execute, and rINST should be already loaded with
9598 * the next opcode word, and r0 holds a pointer to the jit profile
9599 * table (pJitProfTable).
9600 */
9601common_testUpdateProfile:
9602    cmp     r0,#0
9603    GET_INST_OPCODE(ip)
9604    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9605
9606common_updateProfile:
9607    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9608    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9609    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9610    GET_INST_OPCODE(ip)
9611    subs    r1,r1,#1           @ decrement counter
9612    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9613    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9614
9615/*
9616 * Here, we switch to the debug interpreter to request
9617 * trace selection.  First, though, check to see if there
9618 * is already a native translation in place (and, if so,
9619 * jump to it now).
9620 */
9621    GET_JIT_THRESHOLD(r1)
9622    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9623    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9624    EXPORT_PC()
9625    mov     r0,rPC
9626    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9627    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9628    mov     r1, rPC                     @ arg1 of translation may need this
9629    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9630    cmp     r0,#0
9631#if !defined(WITH_SELF_VERIFICATION)
9632    bxne    r0                          @ jump to the translation
9633    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9634    @ fall-through to common_selectTrace
9635#else
9636    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9637    beq     common_selectTrace
9638    /*
9639     * At this point, we have a target translation.  However, if
9640     * that translation is actually the interpret-only pseudo-translation
9641     * we want to treat it the same as no translation.
9642     */
9643    mov     r10, r0                     @ save target
9644    bl      dvmCompilerGetInterpretTemplate
9645    cmp     r0, r10                     @ special case?
9646    bne     jitSVShadowRunStart         @ set up self verification shadow space
9647    GET_INST_OPCODE(ip)
9648    GOTO_OPCODE(ip)
9649    /* no return */
9650#endif
9651
9652/*
9653 * On entry:
9654 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9655 */
9656common_selectTrace:
9657    str     r2,[rGLUE,#offGlue_jitState]
9658    mov     r2,#kInterpEntryInstr       @ normal entry reason
9659    str     r2,[rGLUE,#offGlue_entryPoint]
9660    mov     r1,#1                       @ set changeInterp
9661    b       common_gotoBail
9662
9663#if defined(WITH_SELF_VERIFICATION)
9664/*
9665 * Save PC and registers to shadow memory for self verification mode
9666 * before jumping to native translation.
9667 * On entry:
9668 *    rPC, rFP, rGLUE: the values that they should contain
9669 *    r10: the address of the target translation.
9670 */
9671jitSVShadowRunStart:
9672    mov     r0,rPC                      @ r0<- program counter
9673    mov     r1,rFP                      @ r1<- frame pointer
9674    mov     r2,rGLUE                    @ r2<- InterpState pointer
9675    mov     r3,r10                      @ r3<- target translation
9676    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9677    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9678    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9679    bx      r10                         @ jump to the translation
9680
9681/*
9682 * Restore PC, registers, and interpState to original values
9683 * before jumping back to the interpreter.
9684 */
9685jitSVShadowRunEnd:
9686    mov    r1,rFP                        @ pass ending fp
9687    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9688    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9689    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9690    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9691    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9692    cmp    r1,#0                         @ check for punt condition
9693    beq    1f
9694    mov    r2,#kJitSelfVerification      @ ask for self verification
9695    str    r2,[rGLUE,#offGlue_jitState]
9696    mov    r2,#kInterpEntryInstr         @ normal entry reason
9697    str    r2,[rGLUE,#offGlue_entryPoint]
9698    mov    r1,#1                         @ set changeInterp
9699    b      common_gotoBail
9700
97011:                                       @ exit to interpreter without check
9702    EXPORT_PC()
9703    adrl   rIBASE, dvmAsmInstructionStart
9704    FETCH_INST()
9705    GET_INST_OPCODE(ip)
9706    GOTO_OPCODE(ip)
9707#endif
9708
9709#endif
9710
9711/*
9712 * Common code when a backward branch is taken.
9713 *
9714 * TODO: we could avoid a branch by just setting r0 and falling through
9715 * into the common_periodicChecks code, and having a test on r0 at the
9716 * end determine if we should return to the caller or update & branch to
9717 * the next instr.
9718 *
9719 * On entry:
9720 *  r9 is PC adjustment *in bytes*
9721 */
9722common_backwardBranch:
9723    mov     r0, #kInterpEntryInstr
9724    bl      common_periodicChecks
9725#if defined(WITH_JIT)
9726    GET_JIT_PROF_TABLE(r0)
9727    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9728    cmp     r0,#0
9729    bne     common_updateProfile
9730    GET_INST_OPCODE(ip)
9731    GOTO_OPCODE(ip)
9732#else
9733    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9734    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9735    GOTO_OPCODE(ip)                     @ jump to next instruction
9736#endif
9737
9738
9739/*
9740 * Need to see if the thread needs to be suspended or debugger/profiler
9741 * activity has begun.  If so, we suspend the thread or side-exit to
9742 * the debug interpreter as appropriate.
9743 *
9744 * The common case is no activity on any of these, so we want to figure
9745 * that out quickly.  If something is up, we can then sort out what.
9746 *
9747 * We want to be fast if the VM was built without debugger or profiler
9748 * support, but we also need to recognize that the system is usually
9749 * shipped with both of these enabled.
9750 *
9751 * TODO: reduce this so we're just checking a single location.
9752 *
9753 * On entry:
9754 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9755 *  r9 is trampoline PC adjustment *in bytes*
9756 */
9757common_periodicChecks:
9758    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9759
9760#if defined(WITH_DEBUGGER)
9761    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9762#endif
9763#if defined(WITH_PROFILER)
9764    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9765#endif
9766
9767    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9768
9769#if defined(WITH_DEBUGGER) && defined(WITH_PROFILER)
9770    cmp     r1, #0                      @ debugger enabled?
9771    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9772    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9773    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9774    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9775#elif defined(WITH_DEBUGGER)
9776    cmp     r1, #0                      @ debugger enabled?
9777    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9778    orrsne  ip, ip, r1                  @ yes, ip<- suspend | debugger; set Z
9779    @ (if not enabled, Z was set by test for r1==0, which is what we want)
9780#elif defined (WITH_PROFILER)
9781    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9782    orrs    ip, ip, r2                  @ ip<- suspendCount | activeProfilers
9783#else
9784    cmp     ip, #0                      @ not ORing anything in; set Z
9785#endif
9786
9787    bxeq    lr                          @ all zero, return
9788
9789    /*
9790     * One or more interesting events have happened.  Figure out what.
9791     *
9792     * If debugging or profiling are compiled in, we need to disambiguate.
9793     *
9794     * r0 still holds the reentry type.
9795     */
9796#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9797    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9798    cmp     ip, #0                      @ want suspend?
9799    beq     1f                          @ no, must be debugger/profiler
9800#endif
9801
9802    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9803#if defined(WITH_JIT)
9804    /*
9805     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9806     * doubles as the Jit's on/off switch.
9807     */
9808    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9809    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9810    ldr     r3, [r3] @ r3 <- pJitProfTable
9811    EXPORT_PC()                         @ need for precise GC
9812    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9813#else
9814    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9815    EXPORT_PC()                         @ need for precise GC
9816#endif
9817    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9818    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9819
9820#if defined(WITH_DEBUGGER) || defined(WITH_PROFILER)
9821
9822    /*
9823     * Reload the debugger/profiler enable flags.  We're checking to see
9824     * if either of these got set while we were suspended.
9825     *
9826     * We can't really avoid the #ifdefs here, because the fields don't
9827     * exist when the feature is disabled.
9828     */
9829#if defined(WITH_DEBUGGER)
9830    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9831    cmp     r1, #0                      @ debugger enabled?
9832    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9833#else
9834    mov     r1, #0
9835#endif
9836#if defined(WITH_PROFILER)
9837    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9838    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9839#else
9840    mov     r2, #0
9841#endif
9842
9843    orrs    r1, r1, r2
9844    beq     2f
9845
98461:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9847    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9848    add     rPC, rPC, r9                @ update rPC
9849    mov     r1, #1                      @ "want switch" = true
9850    b       common_gotoBail             @ side exit
9851
9852#endif /*WITH_DEBUGGER || WITH_PROFILER*/
9853
98542:
9855    bx      lr                          @ nothing to do, return
9856
9857
9858/*
9859 * The equivalent of "goto bail", this calls through the "bail handler".
9860 *
9861 * State registers will be saved to the "glue" area before bailing.
9862 *
9863 * On entry:
9864 *  r1 is "bool changeInterp", indicating if we want to switch to the
9865 *     other interpreter or just bail all the way out
9866 */
9867common_gotoBail:
9868    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9869    mov     r0, rGLUE                   @ r0<- glue ptr
9870    b       dvmMterpStdBail             @ call(glue, changeInterp)
9871
9872    @add     r1, r1, #1                  @ using (boolean+1)
9873    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9874    @bl      _longjmp                    @ does not return
9875    @bl      common_abort
9876
9877
9878/*
9879 * Common code for method invocation with range.
9880 *
9881 * On entry:
9882 *  r0 is "Method* methodToCall", the method we're trying to call
9883 */
9884common_invokeMethodRange:
9885.LinvokeNewRange:
9886    @ prepare to copy args to "outs" area of current frame
9887    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9888    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9889    beq     .LinvokeArgsDone            @ if no args, skip the rest
9890    FETCH(r1, 2)                        @ r1<- CCCC
9891
9892    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9893    @ (very few methods have > 10 args; could unroll for common cases)
9894    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9895    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9896    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
98971:  ldr     r1, [r3], #4                @ val = *fp++
9898    subs    r2, r2, #1                  @ count--
9899    str     r1, [r10], #4               @ *outs++ = val
9900    bne     1b                          @ ...while count != 0
9901    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9902    b       .LinvokeArgsDone
9903
9904/*
9905 * Common code for method invocation without range.
9906 *
9907 * On entry:
9908 *  r0 is "Method* methodToCall", the method we're trying to call
9909 */
9910common_invokeMethodNoRange:
9911.LinvokeNewNoRange:
9912    @ prepare to copy args to "outs" area of current frame
9913    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9914    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9915    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9916    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9917    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9918    beq     .LinvokeArgsDone
9919
9920    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9921.LinvokeNonRange:
9922    rsb     r2, r2, #5                  @ r2<- 5-r2
9923    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9924    bl      common_abort                @ (skipped due to ARM prefetch)
99255:  and     ip, rINST, #0x0f00          @ isolate A
9926    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9927    mov     r0, r0                      @ nop
9928    str     r2, [r10, #-4]!             @ *--outs = vA
99294:  and     ip, r1, #0xf000             @ isolate G
9930    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9931    mov     r0, r0                      @ nop
9932    str     r2, [r10, #-4]!             @ *--outs = vG
99333:  and     ip, r1, #0x0f00             @ isolate F
9934    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9935    mov     r0, r0                      @ nop
9936    str     r2, [r10, #-4]!             @ *--outs = vF
99372:  and     ip, r1, #0x00f0             @ isolate E
9938    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9939    mov     r0, r0                      @ nop
9940    str     r2, [r10, #-4]!             @ *--outs = vE
99411:  and     ip, r1, #0x000f             @ isolate D
9942    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9943    mov     r0, r0                      @ nop
9944    str     r2, [r10, #-4]!             @ *--outs = vD
99450:  @ fall through to .LinvokeArgsDone
9946
9947.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9948    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9949    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9950    @ find space for the new stack frame, check for overflow
9951    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9952    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9953    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9954@    bl      common_dumpRegs
9955    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9956    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9957    cmp     r3, r9                      @ bottom < interpStackEnd?
9958    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9959    blo     .LstackOverflow             @ yes, this frame will overflow stack
9960
9961    @ set up newSaveArea
9962#ifdef EASY_GDB
9963    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
9964    str     ip, [r10, #offStackSaveArea_prevSave]
9965#endif
9966    str     rFP, [r10, #offStackSaveArea_prevFrame]
9967    str     rPC, [r10, #offStackSaveArea_savedPc]
9968#if defined(WITH_JIT)
9969    mov     r9, #0
9970    str     r9, [r10, #offStackSaveArea_returnAddr]
9971#endif
9972    str     r0, [r10, #offStackSaveArea_method]
9973    tst     r3, #ACC_NATIVE
9974    bne     .LinvokeNative
9975
9976    /*
9977    stmfd   sp!, {r0-r3}
9978    bl      common_printNewline
9979    mov     r0, rFP
9980    mov     r1, #0
9981    bl      dvmDumpFp
9982    ldmfd   sp!, {r0-r3}
9983    stmfd   sp!, {r0-r3}
9984    mov     r0, r1
9985    mov     r1, r10
9986    bl      dvmDumpFp
9987    bl      common_printNewline
9988    ldmfd   sp!, {r0-r3}
9989    */
9990
9991    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
9992    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
9993    mov     rPC, r2                         @ publish new rPC
9994    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
9995
9996    @ Update "glue" values for the new method
9997    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
9998    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
9999    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10000#if defined(WITH_JIT)
10001    GET_JIT_PROF_TABLE(r0)
10002    mov     rFP, r1                         @ fp = newFp
10003    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10004    mov     rINST, r9                       @ publish new rINST
10005    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10006    cmp     r0,#0
10007    bne     common_updateProfile
10008    GOTO_OPCODE(ip)                         @ jump to next instruction
10009#else
10010    mov     rFP, r1                         @ fp = newFp
10011    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10012    mov     rINST, r9                       @ publish new rINST
10013    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10014    GOTO_OPCODE(ip)                         @ jump to next instruction
10015#endif
10016
10017.LinvokeNative:
10018    @ Prep for the native call
10019    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10020    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10021    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10022    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10023    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10024    mov     r9, r3                      @ r9<- glue->self (preserve)
10025
10026    mov     r2, r0                      @ r2<- methodToCall
10027    mov     r0, r1                      @ r0<- newFp (points to args)
10028    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10029
10030#ifdef ASSIST_DEBUGGER
10031    /* insert fake function header to help gdb find the stack frame */
10032    b       .Lskip
10033    .type   dalvik_mterp, %function
10034dalvik_mterp:
10035    .fnstart
10036    MTERP_ENTRY1
10037    MTERP_ENTRY2
10038.Lskip:
10039#endif
10040
10041    @mov     lr, pc                      @ set return addr
10042    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10043    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10044
10045#if defined(WITH_JIT)
10046    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10047#endif
10048
10049    @ native return; r9=self, r10=newSaveArea
10050    @ equivalent to dvmPopJniLocals
10051    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10052    ldr     r1, [r9, #offThread_exception] @ check for exception
10053#if defined(WITH_JIT)
10054    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10055#endif
10056    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10057    cmp     r1, #0                      @ null?
10058    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10059#if defined(WITH_JIT)
10060    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10061#endif
10062    bne     common_exceptionThrown      @ no, handle exception
10063
10064    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10065    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10066    GOTO_OPCODE(ip)                     @ jump to next instruction
10067
10068.LstackOverflow:    @ r0=methodToCall
10069    mov     r1, r0                      @ r1<- methodToCall
10070    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10071    bl      dvmHandleStackOverflow
10072    b       common_exceptionThrown
10073#ifdef ASSIST_DEBUGGER
10074    .fnend
10075#endif
10076
10077
10078    /*
10079     * Common code for method invocation, calling through "glue code".
10080     *
10081     * TODO: now that we have range and non-range invoke handlers, this
10082     *       needs to be split into two.  Maybe just create entry points
10083     *       that set r9 and jump here?
10084     *
10085     * On entry:
10086     *  r0 is "Method* methodToCall", the method we're trying to call
10087     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10088     */
10089     .if    0
10090.LinvokeOld:
10091    sub     sp, sp, #8                  @ space for args + pad
10092    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10093    mov     r2, r0                      @ A2<- methodToCall
10094    mov     r0, rGLUE                   @ A0<- glue
10095    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10096    mov     r1, r9                      @ A1<- methodCallRange
10097    mov     r3, rINST, lsr #8           @ A3<- AA
10098    str     ip, [sp, #0]                @ A4<- ip
10099    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10100    add     sp, sp, #8                  @ remove arg area
10101    b       common_resumeAfterGlueCall  @ continue to next instruction
10102    .endif
10103
10104
10105
10106/*
10107 * Common code for handling a return instruction.
10108 *
10109 * This does not return.
10110 */
10111common_returnFromMethod:
10112.LreturnNew:
10113    mov     r0, #kInterpEntryReturn
10114    mov     r9, #0
10115    bl      common_periodicChecks
10116
10117    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10118    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10119    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10120    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10121                                        @ r2<- method we're returning to
10122    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10123    cmp     r2, #0                      @ is this a break frame?
10124    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10125    mov     r1, #0                      @ "want switch" = false
10126    beq     common_gotoBail             @ break frame, bail out completely
10127
10128    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10129    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10130    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10131    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10132#if defined(WITH_JIT)
10133    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10134    GET_JIT_PROF_TABLE(r0)
10135    mov     rPC, r9                     @ publish new rPC
10136    str     r1, [rGLUE, #offGlue_methodClassDex]
10137    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10138    cmp     r10, #0                      @ caller is compiled code
10139    blxne   r10
10140    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10141    cmp     r0,#0
10142    bne     common_updateProfile
10143    GOTO_OPCODE(ip)                     @ jump to next instruction
10144#else
10145    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10146    mov     rPC, r9                     @ publish new rPC
10147    str     r1, [rGLUE, #offGlue_methodClassDex]
10148    GOTO_OPCODE(ip)                     @ jump to next instruction
10149#endif
10150
10151    /*
10152     * Return handling, calls through "glue code".
10153     */
10154     .if    0
10155.LreturnOld:
10156    SAVE_PC_FP_TO_GLUE()                @ export state
10157    mov     r0, rGLUE                   @ arg to function
10158    bl      dvmMterp_returnFromMethod
10159    b       common_resumeAfterGlueCall
10160    .endif
10161
10162
10163/*
10164 * Somebody has thrown an exception.  Handle it.
10165 *
10166 * If the exception processing code returns to us (instead of falling
10167 * out of the interpreter), continue with whatever the next instruction
10168 * now happens to be.
10169 *
10170 * This does not return.
10171 */
10172     .global dvmMterpCommonExceptionThrown
10173dvmMterpCommonExceptionThrown:
10174common_exceptionThrown:
10175.LexceptionNew:
10176    mov     r0, #kInterpEntryThrow
10177    mov     r9, #0
10178    bl      common_periodicChecks
10179
10180    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10181    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10182    mov     r1, r10                     @ r1<- self
10183    mov     r0, r9                      @ r0<- exception
10184    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10185    mov     r3, #0                      @ r3<- NULL
10186    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10187
10188    /* set up args and a local for "&fp" */
10189    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10190    str     rFP, [sp, #-4]!             @ *--sp = fp
10191    mov     ip, sp                      @ ip<- &fp
10192    mov     r3, #0                      @ r3<- false
10193    str     ip, [sp, #-4]!              @ *--sp = &fp
10194    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10195    mov     r0, r10                     @ r0<- self
10196    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10197    mov     r2, r9                      @ r2<- exception
10198    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10199    mov     r1, r1, asr #1              @ r1<- offset in code units
10200
10201    /* call, r0 gets catchRelPc (a code-unit offset) */
10202    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10203
10204    /* fix earlier stack overflow if necessary; may trash rFP */
10205    ldrb    r1, [r10, #offThread_stackOverflowed]
10206    cmp     r1, #0                      @ did we overflow earlier?
10207    beq     1f                          @ no, skip ahead
10208    mov     rFP, r0                     @ save relPc result in rFP
10209    mov     r0, r10                     @ r0<- self
10210    mov     r1, r9                      @ r1<- exception
10211    bl      dvmCleanupStackOverflow     @ call(self)
10212    mov     r0, rFP                     @ restore result
102131:
10214
10215    /* update frame pointer and check result from dvmFindCatchBlock */
10216    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10217    cmp     r0, #0                      @ is catchRelPc < 0?
10218    add     sp, sp, #8                  @ restore stack
10219    bmi     .LnotCaughtLocally
10220
10221    /* adjust locals to match self->curFrame and updated PC */
10222    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10223    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10224    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10225    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10226    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10227    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10228    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10229    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10230
10231    /* release the tracked alloc on the exception */
10232    mov     r0, r9                      @ r0<- exception
10233    mov     r1, r10                     @ r1<- self
10234    bl      dvmReleaseTrackedAlloc      @ release the exception
10235
10236    /* restore the exception if the handler wants it */
10237    FETCH_INST()                        @ load rINST from rPC
10238    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10239    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10240    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10241    GOTO_OPCODE(ip)                     @ jump to next instruction
10242
10243.LnotCaughtLocally: @ r9=exception, r10=self
10244    /* fix stack overflow if necessary */
10245    ldrb    r1, [r10, #offThread_stackOverflowed]
10246    cmp     r1, #0                      @ did we overflow earlier?
10247    movne   r0, r10                     @ if yes: r0<- self
10248    movne   r1, r9                      @ if yes: r1<- exception
10249    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10250
10251    @ may want to show "not caught locally" debug messages here
10252#if DVM_SHOW_EXCEPTION >= 2
10253    /* call __android_log_print(prio, tag, format, ...) */
10254    /* "Exception %s from %s:%d not caught locally" */
10255    @ dvmLineNumFromPC(method, pc - method->insns)
10256    ldr     r0, [rGLUE, #offGlue_method]
10257    ldr     r1, [r0, #offMethod_insns]
10258    sub     r1, rPC, r1
10259    asr     r1, r1, #1
10260    bl      dvmLineNumFromPC
10261    str     r0, [sp, #-4]!
10262    @ dvmGetMethodSourceFile(method)
10263    ldr     r0, [rGLUE, #offGlue_method]
10264    bl      dvmGetMethodSourceFile
10265    str     r0, [sp, #-4]!
10266    @ exception->clazz->descriptor
10267    ldr     r3, [r9, #offObject_clazz]
10268    ldr     r3, [r3, #offClassObject_descriptor]
10269    @
10270    ldr     r2, strExceptionNotCaughtLocally
10271    ldr     r1, strLogTag
10272    mov     r0, #3                      @ LOG_DEBUG
10273    bl      __android_log_print
10274#endif
10275    str     r9, [r10, #offThread_exception] @ restore exception
10276    mov     r0, r9                      @ r0<- exception
10277    mov     r1, r10                     @ r1<- self
10278    bl      dvmReleaseTrackedAlloc      @ release the exception
10279    mov     r1, #0                      @ "want switch" = false
10280    b       common_gotoBail             @ bail out
10281
10282
10283    /*
10284     * Exception handling, calls through "glue code".
10285     */
10286    .if     0
10287.LexceptionOld:
10288    SAVE_PC_FP_TO_GLUE()                @ export state
10289    mov     r0, rGLUE                   @ arg to function
10290    bl      dvmMterp_exceptionThrown
10291    b       common_resumeAfterGlueCall
10292    .endif
10293
10294
10295/*
10296 * After returning from a "glued" function, pull out the updated
10297 * values and start executing at the next instruction.
10298 */
10299common_resumeAfterGlueCall:
10300    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10301    FETCH_INST()                        @ load rINST from rPC
10302    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10303    GOTO_OPCODE(ip)                     @ jump to next instruction
10304
10305/*
10306 * Invalid array index.
10307 */
10308common_errArrayIndex:
10309    EXPORT_PC()
10310    ldr     r0, strArrayIndexException
10311    mov     r1, #0
10312    bl      dvmThrowException
10313    b       common_exceptionThrown
10314
10315/*
10316 * Invalid array value.
10317 */
10318common_errArrayStore:
10319    EXPORT_PC()
10320    ldr     r0, strArrayStoreException
10321    mov     r1, #0
10322    bl      dvmThrowException
10323    b       common_exceptionThrown
10324
10325/*
10326 * Integer divide or mod by zero.
10327 */
10328common_errDivideByZero:
10329    EXPORT_PC()
10330    ldr     r0, strArithmeticException
10331    ldr     r1, strDivideByZero
10332    bl      dvmThrowException
10333    b       common_exceptionThrown
10334
10335/*
10336 * Attempt to allocate an array with a negative size.
10337 */
10338common_errNegativeArraySize:
10339    EXPORT_PC()
10340    ldr     r0, strNegativeArraySizeException
10341    mov     r1, #0
10342    bl      dvmThrowException
10343    b       common_exceptionThrown
10344
10345/*
10346 * Invocation of a non-existent method.
10347 */
10348common_errNoSuchMethod:
10349    EXPORT_PC()
10350    ldr     r0, strNoSuchMethodError
10351    mov     r1, #0
10352    bl      dvmThrowException
10353    b       common_exceptionThrown
10354
10355/*
10356 * We encountered a null object when we weren't expecting one.  We
10357 * export the PC, throw a NullPointerException, and goto the exception
10358 * processing code.
10359 */
10360common_errNullObject:
10361    EXPORT_PC()
10362    ldr     r0, strNullPointerException
10363    mov     r1, #0
10364    bl      dvmThrowException
10365    b       common_exceptionThrown
10366
10367/*
10368 * For debugging, cause an immediate fault.  The source address will
10369 * be in lr (use a bl instruction to jump here).
10370 */
10371common_abort:
10372    ldr     pc, .LdeadFood
10373.LdeadFood:
10374    .word   0xdeadf00d
10375
10376/*
10377 * Spit out a "we were here", preserving all registers.  (The attempt
10378 * to save ip won't work, but we need to save an even number of
10379 * registers for EABI 64-bit stack alignment.)
10380 */
10381    .macro  SQUEAK num
10382common_squeak\num:
10383    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10384    ldr     r0, strSqueak
10385    mov     r1, #\num
10386    bl      printf
10387    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10388    bx      lr
10389    .endm
10390
10391    SQUEAK  0
10392    SQUEAK  1
10393    SQUEAK  2
10394    SQUEAK  3
10395    SQUEAK  4
10396    SQUEAK  5
10397
10398/*
10399 * Spit out the number in r0, preserving registers.
10400 */
10401common_printNum:
10402    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10403    mov     r1, r0
10404    ldr     r0, strSqueak
10405    bl      printf
10406    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10407    bx      lr
10408
10409/*
10410 * Print a newline, preserving registers.
10411 */
10412common_printNewline:
10413    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10414    ldr     r0, strNewline
10415    bl      printf
10416    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10417    bx      lr
10418
10419    /*
10420     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10421     */
10422common_printHex:
10423    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10424    mov     r1, r0
10425    ldr     r0, strPrintHex
10426    bl      printf
10427    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10428    bx      lr
10429
10430/*
10431 * Print the 64-bit quantity in r0-r1, preserving registers.
10432 */
10433common_printLong:
10434    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10435    mov     r3, r1
10436    mov     r2, r0
10437    ldr     r0, strPrintLong
10438    bl      printf
10439    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10440    bx      lr
10441
10442/*
10443 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10444 */
10445common_printMethod:
10446    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10447    bl      dvmMterpPrintMethod
10448    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10449    bx      lr
10450
10451/*
10452 * Call a C helper function that dumps regs and possibly some
10453 * additional info.  Requires the C function to be compiled in.
10454 */
10455    .if     0
10456common_dumpRegs:
10457    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10458    bl      dvmMterpDumpArmRegs
10459    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10460    bx      lr
10461    .endif
10462
10463#if 0
10464/*
10465 * Experiment on VFP mode.
10466 *
10467 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10468 *
10469 * Updates the bits specified by "mask", setting them to the values in "val".
10470 */
10471setFPSCR:
10472    and     r0, r0, r1                  @ make sure no stray bits are set
10473    fmrx    r2, fpscr                   @ get VFP reg
10474    mvn     r1, r1                      @ bit-invert mask
10475    and     r2, r2, r1                  @ clear masked bits
10476    orr     r2, r2, r0                  @ set specified bits
10477    fmxr    fpscr, r2                   @ set VFP reg
10478    mov     r0, r2                      @ return new value
10479    bx      lr
10480
10481    .align  2
10482    .global dvmConfigureFP
10483    .type   dvmConfigureFP, %function
10484dvmConfigureFP:
10485    stmfd   sp!, {ip, lr}
10486    /* 0x03000000 sets DN/FZ */
10487    /* 0x00009f00 clears the six exception enable flags */
10488    bl      common_squeak0
10489    mov     r0, #0x03000000             @ r0<- 0x03000000
10490    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10491    bl      setFPSCR
10492    ldmfd   sp!, {ip, pc}
10493#endif
10494
10495
10496/*
10497 * String references, must be close to the code that uses them.
10498 */
10499    .align  2
10500strArithmeticException:
10501    .word   .LstrArithmeticException
10502strArrayIndexException:
10503    .word   .LstrArrayIndexException
10504strArrayStoreException:
10505    .word   .LstrArrayStoreException
10506strDivideByZero:
10507    .word   .LstrDivideByZero
10508strNegativeArraySizeException:
10509    .word   .LstrNegativeArraySizeException
10510strNoSuchMethodError:
10511    .word   .LstrNoSuchMethodError
10512strNullPointerException:
10513    .word   .LstrNullPointerException
10514
10515strLogTag:
10516    .word   .LstrLogTag
10517strExceptionNotCaughtLocally:
10518    .word   .LstrExceptionNotCaughtLocally
10519
10520strNewline:
10521    .word   .LstrNewline
10522strSqueak:
10523    .word   .LstrSqueak
10524strPrintHex:
10525    .word   .LstrPrintHex
10526strPrintLong:
10527    .word   .LstrPrintLong
10528
10529/*
10530 * Zero-terminated ASCII string data.
10531 *
10532 * On ARM we have two choices: do like gcc does, and LDR from a .word
10533 * with the address, or use an ADR pseudo-op to get the address
10534 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10535 * PC-relative addressing mode and hence has a limited range, which
10536 * makes it not work well with mergeable string sections.
10537 */
10538    .section .rodata.str1.4,"aMS",%progbits,1
10539
10540.LstrBadEntryPoint:
10541    .asciz  "Bad entry point %d\n"
10542.LstrArithmeticException:
10543    .asciz  "Ljava/lang/ArithmeticException;"
10544.LstrArrayIndexException:
10545    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10546.LstrArrayStoreException:
10547    .asciz  "Ljava/lang/ArrayStoreException;"
10548.LstrClassCastException:
10549    .asciz  "Ljava/lang/ClassCastException;"
10550.LstrDivideByZero:
10551    .asciz  "divide by zero"
10552.LstrFilledNewArrayNotImpl:
10553    .asciz  "filled-new-array only implemented for objects and 'int'"
10554.LstrInternalError:
10555    .asciz  "Ljava/lang/InternalError;"
10556.LstrInstantiationError:
10557    .asciz  "Ljava/lang/InstantiationError;"
10558.LstrNegativeArraySizeException:
10559    .asciz  "Ljava/lang/NegativeArraySizeException;"
10560.LstrNoSuchMethodError:
10561    .asciz  "Ljava/lang/NoSuchMethodError;"
10562.LstrNullPointerException:
10563    .asciz  "Ljava/lang/NullPointerException;"
10564
10565.LstrLogTag:
10566    .asciz  "mterp"
10567.LstrExceptionNotCaughtLocally:
10568    .asciz  "Exception %s from %s:%d not caught locally\n"
10569
10570.LstrNewline:
10571    .asciz  "\n"
10572.LstrSqueak:
10573    .asciz  "<%d>"
10574.LstrPrintHex:
10575    .asciz  "<0x%x>"
10576.LstrPrintLong:
10577    .asciz  "<%lld>"
10578
10579