InterpAsm-armv5te-vfp.S revision b78c76f88ea42e7a3b295c210ca9ee86e7290043
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
250.endm
251
252/* File: armv5te/entry.S */
253/*
254 * Copyright (C) 2008 The Android Open Source Project
255 *
256 * Licensed under the Apache License, Version 2.0 (the "License");
257 * you may not use this file except in compliance with the License.
258 * You may obtain a copy of the License at
259 *
260 *      http://www.apache.org/licenses/LICENSE-2.0
261 *
262 * Unless required by applicable law or agreed to in writing, software
263 * distributed under the License is distributed on an "AS IS" BASIS,
264 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
265 * See the License for the specific language governing permissions and
266 * limitations under the License.
267 */
268/*
269 * Interpreter entry point.
270 */
271
272/*
273 * We don't have formal stack frames, so gdb scans upward in the code
274 * to find the start of the function (a label with the %function type),
275 * and then looks at the next few instructions to figure out what
276 * got pushed onto the stack.  From this it figures out how to restore
277 * the registers, including PC, for the previous stack frame.  If gdb
278 * sees a non-function label, it stops scanning, so either we need to
279 * have nothing but assembler-local labels between the entry point and
280 * the break, or we need to fake it out.
281 *
282 * When this is defined, we add some stuff to make gdb less confused.
283 */
284#define ASSIST_DEBUGGER 1
285
286    .text
287    .align  2
288    .global dvmMterpStdRun
289    .type   dvmMterpStdRun, %function
290
291/*
292 * On entry:
293 *  r0  MterpGlue* glue
294 *
295 * This function returns a boolean "changeInterp" value.  The return comes
296 * via a call to dvmMterpStdBail().
297 */
298dvmMterpStdRun:
299#define MTERP_ENTRY1 \
300    .save {r4-r10,fp,lr}; \
301    stmfd   sp!, {r4-r10,fp,lr}         @ save 9 regs
302#define MTERP_ENTRY2 \
303    .pad    #4; \
304    sub     sp, sp, #4                  @ align 64
305
306    .fnstart
307    MTERP_ENTRY1
308    MTERP_ENTRY2
309
310    /* save stack pointer, add magic word for debuggerd */
311    str     sp, [r0, #offGlue_bailPtr]  @ save SP for eventual return
312
313    /* set up "named" registers, figure out entry point */
314    mov     rGLUE, r0                   @ set rGLUE
315    ldr     r1, [r0, #offGlue_entryPoint]   @ enum is 4 bytes in aapcs-EABI
316    LOAD_PC_FP_FROM_GLUE()              @ load rPC and rFP from "glue"
317    adr     rIBASE, dvmAsmInstructionStart  @ set rIBASE
318    cmp     r1, #kInterpEntryInstr      @ usual case?
319    bne     .Lnot_instr                 @ no, handle it
320
321#if defined(WITH_JIT)
322.LentryInstr:
323    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
324    /* Entry is always a possible trace start */
325    GET_JIT_PROF_TABLE(r0)
326    FETCH_INST()
327    mov     r1, #0                      @ prepare the value for the new state
328    str     r1, [r10, #offThread_inJitCodeCache] @ back to the interp land
329    cmp     r0,#0                       @ is profiling disabled?
330#if !defined(WITH_SELF_VERIFICATION)
331    bne     common_updateProfile        @ profiling is enabled
332#else
333    ldr     r2, [r10, #offThread_shadowSpace]   @ to find out the jit exit state
334    beq     1f                          @ profiling is disabled
335    ldr     r3, [r2, #offShadowSpace_jitExitState]  @ jit exit state
336    cmp     r3, #kSVSTraceSelect        @ hot trace following?
337    moveq   r2,#kJitTSelectRequestHot   @ ask for trace selection
338    beq     common_selectTrace          @ go build the trace
339    cmp     r3, #kSVSNoProfile          @ don't profile the next instruction?
340    beq     1f                          @ intrepret the next instruction
341    b       common_updateProfile        @ collect profiles
342#endif
3431:
344    GET_INST_OPCODE(ip)
345    GOTO_OPCODE(ip)
346#else
347    /* start executing the instruction at rPC */
348    FETCH_INST()                        @ load rINST from rPC
349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
350    GOTO_OPCODE(ip)                     @ jump to next instruction
351#endif
352
353.Lnot_instr:
354    cmp     r1, #kInterpEntryReturn     @ were we returning from a method?
355    beq     common_returnFromMethod
356
357.Lnot_return:
358    cmp     r1, #kInterpEntryThrow      @ were we throwing an exception?
359    beq     common_exceptionThrown
360
361#if defined(WITH_JIT)
362.Lnot_throw:
363    ldr     r10,[rGLUE, #offGlue_jitResumeNPC]
364    ldr     r2,[rGLUE, #offGlue_jitResumeDPC]
365    cmp     r1, #kInterpEntryResume     @ resuming after Jit single-step?
366    bne     .Lbad_arg
367    cmp     rPC,r2
368    bne     .LentryInstr                @ must have branched, don't resume
369#if defined(WITH_SELF_VERIFICATION)
370    @ glue->entryPoint will be set in dvmSelfVerificationSaveState
371    b       jitSVShadowRunStart         @ re-enter the translation after the
372                                        @ single-stepped instruction
373    @noreturn
374#endif
375    mov     r1, #kInterpEntryInstr
376    str     r1, [rGLUE, #offGlue_entryPoint]
377    bx      r10                         @ re-enter the translation
378#endif
379
380.Lbad_arg:
381    ldr     r0, strBadEntryPoint
382    @ r1 holds value of entryPoint
383    bl      printf
384    bl      dvmAbort
385    .fnend
386
387
388    .global dvmMterpStdBail
389    .type   dvmMterpStdBail, %function
390
391/*
392 * Restore the stack pointer and PC from the save point established on entry.
393 * This is essentially the same as a longjmp, but should be cheaper.  The
394 * last instruction causes us to return to whoever called dvmMterpStdRun.
395 *
396 * We pushed some registers on the stack in dvmMterpStdRun, then saved
397 * SP and LR.  Here we restore SP, restore the registers, and then restore
398 * LR to PC.
399 *
400 * On entry:
401 *  r0  MterpGlue* glue
402 *  r1  bool changeInterp
403 */
404dvmMterpStdBail:
405    ldr     sp, [r0, #offGlue_bailPtr]      @ sp<- saved SP
406    mov     r0, r1                          @ return the changeInterp value
407    add     sp, sp, #4                      @ un-align 64
408    LDMFD_PC "r4-r10,fp"                    @ restore 9 regs and return
409
410
411/*
412 * String references.
413 */
414strBadEntryPoint:
415    .word   .LstrBadEntryPoint
416
417
418    .global dvmAsmInstructionStart
419    .type   dvmAsmInstructionStart, %function
420dvmAsmInstructionStart = .L_OP_NOP
421    .text
422
423/* ------------------------------ */
424    .balign 64
425.L_OP_NOP: /* 0x00 */
426/* File: armv5te/OP_NOP.S */
427    FETCH_ADVANCE_INST(1)               @ advance to next instr, load rINST
428    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
429    GOTO_OPCODE(ip)                     @ execute it
430
431#ifdef ASSIST_DEBUGGER
432    /* insert fake function header to help gdb find the stack frame */
433    .type   dalvik_inst, %function
434dalvik_inst:
435    .fnstart
436    MTERP_ENTRY1
437    MTERP_ENTRY2
438    .fnend
439#endif
440
441/* ------------------------------ */
442    .balign 64
443.L_OP_MOVE: /* 0x01 */
444/* File: armv5te/OP_MOVE.S */
445    /* for move, move-object, long-to-int */
446    /* op vA, vB */
447    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
448    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
449    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
450    GET_VREG(r2, r1)                    @ r2<- fp[B]
451    and     r0, r0, #15
452    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
453    SET_VREG(r2, r0)                    @ fp[A]<- r2
454    GOTO_OPCODE(ip)                     @ execute next instruction
455
456/* ------------------------------ */
457    .balign 64
458.L_OP_MOVE_FROM16: /* 0x02 */
459/* File: armv5te/OP_MOVE_FROM16.S */
460    /* for: move/from16, move-object/from16 */
461    /* op vAA, vBBBB */
462    FETCH(r1, 1)                        @ r1<- BBBB
463    mov     r0, rINST, lsr #8           @ r0<- AA
464    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
465    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
466    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
467    SET_VREG(r2, r0)                    @ fp[AA]<- r2
468    GOTO_OPCODE(ip)                     @ jump to next instruction
469
470/* ------------------------------ */
471    .balign 64
472.L_OP_MOVE_16: /* 0x03 */
473/* File: armv5te/OP_MOVE_16.S */
474    /* for: move/16, move-object/16 */
475    /* op vAAAA, vBBBB */
476    FETCH(r1, 2)                        @ r1<- BBBB
477    FETCH(r0, 1)                        @ r0<- AAAA
478    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
479    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
480    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
481    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
482    GOTO_OPCODE(ip)                     @ jump to next instruction
483
484/* ------------------------------ */
485    .balign 64
486.L_OP_MOVE_WIDE: /* 0x04 */
487/* File: armv5te/OP_MOVE_WIDE.S */
488    /* move-wide vA, vB */
489    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
490    mov     r2, rINST, lsr #8           @ r2<- A(+)
491    mov     r3, rINST, lsr #12          @ r3<- B
492    and     r2, r2, #15
493    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
494    add     r2, rFP, r2, lsl #2         @ r2<- &fp[A]
495    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[B]
496    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
497    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
498    stmia   r2, {r0-r1}                 @ fp[A]<- r0/r1
499    GOTO_OPCODE(ip)                     @ jump to next instruction
500
501/* ------------------------------ */
502    .balign 64
503.L_OP_MOVE_WIDE_FROM16: /* 0x05 */
504/* File: armv5te/OP_MOVE_WIDE_FROM16.S */
505    /* move-wide/from16 vAA, vBBBB */
506    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
507    FETCH(r3, 1)                        @ r3<- BBBB
508    mov     r2, rINST, lsr #8           @ r2<- AA
509    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
510    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
511    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
512    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
514    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
515    GOTO_OPCODE(ip)                     @ jump to next instruction
516
517/* ------------------------------ */
518    .balign 64
519.L_OP_MOVE_WIDE_16: /* 0x06 */
520/* File: armv5te/OP_MOVE_WIDE_16.S */
521    /* move-wide/16 vAAAA, vBBBB */
522    /* NOTE: regs can overlap, e.g. "move v6,v7" or "move v7,v6" */
523    FETCH(r3, 2)                        @ r3<- BBBB
524    FETCH(r2, 1)                        @ r2<- AAAA
525    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BBBB]
526    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AAAA]
527    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[BBBB]
528    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
529    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
530    stmia   r2, {r0-r1}                 @ fp[AAAA]<- r0/r1
531    GOTO_OPCODE(ip)                     @ jump to next instruction
532
533/* ------------------------------ */
534    .balign 64
535.L_OP_MOVE_OBJECT: /* 0x07 */
536/* File: armv5te/OP_MOVE_OBJECT.S */
537/* File: armv5te/OP_MOVE.S */
538    /* for move, move-object, long-to-int */
539    /* op vA, vB */
540    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
541    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
542    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
543    GET_VREG(r2, r1)                    @ r2<- fp[B]
544    and     r0, r0, #15
545    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
546    SET_VREG(r2, r0)                    @ fp[A]<- r2
547    GOTO_OPCODE(ip)                     @ execute next instruction
548
549
550/* ------------------------------ */
551    .balign 64
552.L_OP_MOVE_OBJECT_FROM16: /* 0x08 */
553/* File: armv5te/OP_MOVE_OBJECT_FROM16.S */
554/* File: armv5te/OP_MOVE_FROM16.S */
555    /* for: move/from16, move-object/from16 */
556    /* op vAA, vBBBB */
557    FETCH(r1, 1)                        @ r1<- BBBB
558    mov     r0, rINST, lsr #8           @ r0<- AA
559    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
560    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
561    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
562    SET_VREG(r2, r0)                    @ fp[AA]<- r2
563    GOTO_OPCODE(ip)                     @ jump to next instruction
564
565
566/* ------------------------------ */
567    .balign 64
568.L_OP_MOVE_OBJECT_16: /* 0x09 */
569/* File: armv5te/OP_MOVE_OBJECT_16.S */
570/* File: armv5te/OP_MOVE_16.S */
571    /* for: move/16, move-object/16 */
572    /* op vAAAA, vBBBB */
573    FETCH(r1, 2)                        @ r1<- BBBB
574    FETCH(r0, 1)                        @ r0<- AAAA
575    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
576    GET_VREG(r2, r1)                    @ r2<- fp[BBBB]
577    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
578    SET_VREG(r2, r0)                    @ fp[AAAA]<- r2
579    GOTO_OPCODE(ip)                     @ jump to next instruction
580
581
582/* ------------------------------ */
583    .balign 64
584.L_OP_MOVE_RESULT: /* 0x0a */
585/* File: armv5te/OP_MOVE_RESULT.S */
586    /* for: move-result, move-result-object */
587    /* op vAA */
588    mov     r2, rINST, lsr #8           @ r2<- AA
589    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
590    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
591    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
592    SET_VREG(r0, r2)                    @ fp[AA]<- r0
593    GOTO_OPCODE(ip)                     @ jump to next instruction
594
595/* ------------------------------ */
596    .balign 64
597.L_OP_MOVE_RESULT_WIDE: /* 0x0b */
598/* File: armv5te/OP_MOVE_RESULT_WIDE.S */
599    /* move-result-wide vAA */
600    mov     r2, rINST, lsr #8           @ r2<- AA
601    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
602    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
603    ldmia   r3, {r0-r1}                 @ r0/r1<- retval.j
604    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
605    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
606    stmia   r2, {r0-r1}                 @ fp[AA]<- r0/r1
607    GOTO_OPCODE(ip)                     @ jump to next instruction
608
609/* ------------------------------ */
610    .balign 64
611.L_OP_MOVE_RESULT_OBJECT: /* 0x0c */
612/* File: armv5te/OP_MOVE_RESULT_OBJECT.S */
613/* File: armv5te/OP_MOVE_RESULT.S */
614    /* for: move-result, move-result-object */
615    /* op vAA */
616    mov     r2, rINST, lsr #8           @ r2<- AA
617    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
618    ldr     r0, [rGLUE, #offGlue_retval]    @ r0<- glue->retval.i
619    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
620    SET_VREG(r0, r2)                    @ fp[AA]<- r0
621    GOTO_OPCODE(ip)                     @ jump to next instruction
622
623
624/* ------------------------------ */
625    .balign 64
626.L_OP_MOVE_EXCEPTION: /* 0x0d */
627/* File: armv5te/OP_MOVE_EXCEPTION.S */
628    /* move-exception vAA */
629    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
630    mov     r2, rINST, lsr #8           @ r2<- AA
631    ldr     r3, [r0, #offThread_exception]  @ r3<- dvmGetException bypass
632    mov     r1, #0                      @ r1<- 0
633    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
634    SET_VREG(r3, r2)                    @ fp[AA]<- exception obj
635    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
636    str     r1, [r0, #offThread_exception]  @ dvmClearException bypass
637    GOTO_OPCODE(ip)                     @ jump to next instruction
638
639/* ------------------------------ */
640    .balign 64
641.L_OP_RETURN_VOID: /* 0x0e */
642/* File: armv5te/OP_RETURN_VOID.S */
643    b       common_returnFromMethod
644
645/* ------------------------------ */
646    .balign 64
647.L_OP_RETURN: /* 0x0f */
648/* File: armv5te/OP_RETURN.S */
649    /*
650     * Return a 32-bit value.  Copies the return value into the "glue"
651     * structure, then jumps to the return handler.
652     *
653     * for: return, return-object
654     */
655    /* op vAA */
656    mov     r2, rINST, lsr #8           @ r2<- AA
657    GET_VREG(r0, r2)                    @ r0<- vAA
658    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
659    b       common_returnFromMethod
660
661/* ------------------------------ */
662    .balign 64
663.L_OP_RETURN_WIDE: /* 0x10 */
664/* File: armv5te/OP_RETURN_WIDE.S */
665    /*
666     * Return a 64-bit value.  Copies the return value into the "glue"
667     * structure, then jumps to the return handler.
668     */
669    /* return-wide vAA */
670    mov     r2, rINST, lsr #8           @ r2<- AA
671    add     r2, rFP, r2, lsl #2         @ r2<- &fp[AA]
672    add     r3, rGLUE, #offGlue_retval  @ r3<- &glue->retval
673    ldmia   r2, {r0-r1}                 @ r0/r1 <- vAA/vAA+1
674    stmia   r3, {r0-r1}                 @ retval<- r0/r1
675    b       common_returnFromMethod
676
677/* ------------------------------ */
678    .balign 64
679.L_OP_RETURN_OBJECT: /* 0x11 */
680/* File: armv5te/OP_RETURN_OBJECT.S */
681/* File: armv5te/OP_RETURN.S */
682    /*
683     * Return a 32-bit value.  Copies the return value into the "glue"
684     * structure, then jumps to the return handler.
685     *
686     * for: return, return-object
687     */
688    /* op vAA */
689    mov     r2, rINST, lsr #8           @ r2<- AA
690    GET_VREG(r0, r2)                    @ r0<- vAA
691    str     r0, [rGLUE, #offGlue_retval] @ retval.i <- vAA
692    b       common_returnFromMethod
693
694
695/* ------------------------------ */
696    .balign 64
697.L_OP_CONST_4: /* 0x12 */
698/* File: armv5te/OP_CONST_4.S */
699    /* const/4 vA, #+B */
700    mov     r1, rINST, lsl #16          @ r1<- Bxxx0000
701    mov     r0, rINST, lsr #8           @ r0<- A+
702    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
703    mov     r1, r1, asr #28             @ r1<- sssssssB (sign-extended)
704    and     r0, r0, #15
705    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
706    SET_VREG(r1, r0)                    @ fp[A]<- r1
707    GOTO_OPCODE(ip)                     @ execute next instruction
708
709/* ------------------------------ */
710    .balign 64
711.L_OP_CONST_16: /* 0x13 */
712/* File: armv5te/OP_CONST_16.S */
713    /* const/16 vAA, #+BBBB */
714    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
715    mov     r3, rINST, lsr #8           @ r3<- AA
716    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
717    SET_VREG(r0, r3)                    @ vAA<- r0
718    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
719    GOTO_OPCODE(ip)                     @ jump to next instruction
720
721/* ------------------------------ */
722    .balign 64
723.L_OP_CONST: /* 0x14 */
724/* File: armv5te/OP_CONST.S */
725    /* const vAA, #+BBBBbbbb */
726    mov     r3, rINST, lsr #8           @ r3<- AA
727    FETCH(r0, 1)                        @ r0<- bbbb (low)
728    FETCH(r1, 2)                        @ r1<- BBBB (high)
729    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
730    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
731    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
732    SET_VREG(r0, r3)                    @ vAA<- r0
733    GOTO_OPCODE(ip)                     @ jump to next instruction
734
735/* ------------------------------ */
736    .balign 64
737.L_OP_CONST_HIGH16: /* 0x15 */
738/* File: armv5te/OP_CONST_HIGH16.S */
739    /* const/high16 vAA, #+BBBB0000 */
740    FETCH(r0, 1)                        @ r0<- 0000BBBB (zero-extended)
741    mov     r3, rINST, lsr #8           @ r3<- AA
742    mov     r0, r0, lsl #16             @ r0<- BBBB0000
743    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
744    SET_VREG(r0, r3)                    @ vAA<- r0
745    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
746    GOTO_OPCODE(ip)                     @ jump to next instruction
747
748/* ------------------------------ */
749    .balign 64
750.L_OP_CONST_WIDE_16: /* 0x16 */
751/* File: armv5te/OP_CONST_WIDE_16.S */
752    /* const-wide/16 vAA, #+BBBB */
753    FETCH_S(r0, 1)                      @ r0<- ssssBBBB (sign-extended)
754    mov     r3, rINST, lsr #8           @ r3<- AA
755    mov     r1, r0, asr #31             @ r1<- ssssssss
756    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
757    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
758    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
759    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
760    GOTO_OPCODE(ip)                     @ jump to next instruction
761
762/* ------------------------------ */
763    .balign 64
764.L_OP_CONST_WIDE_32: /* 0x17 */
765/* File: armv5te/OP_CONST_WIDE_32.S */
766    /* const-wide/32 vAA, #+BBBBbbbb */
767    FETCH(r0, 1)                        @ r0<- 0000bbbb (low)
768    mov     r3, rINST, lsr #8           @ r3<- AA
769    FETCH_S(r2, 2)                      @ r2<- ssssBBBB (high)
770    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
771    orr     r0, r0, r2, lsl #16         @ r0<- BBBBbbbb
772    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
773    mov     r1, r0, asr #31             @ r1<- ssssssss
774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
775    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
776    GOTO_OPCODE(ip)                     @ jump to next instruction
777
778/* ------------------------------ */
779    .balign 64
780.L_OP_CONST_WIDE: /* 0x18 */
781/* File: armv5te/OP_CONST_WIDE.S */
782    /* const-wide vAA, #+HHHHhhhhBBBBbbbb */
783    FETCH(r0, 1)                        @ r0<- bbbb (low)
784    FETCH(r1, 2)                        @ r1<- BBBB (low middle)
785    FETCH(r2, 3)                        @ r2<- hhhh (high middle)
786    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb (low word)
787    FETCH(r3, 4)                        @ r3<- HHHH (high)
788    mov     r9, rINST, lsr #8           @ r9<- AA
789    orr     r1, r2, r3, lsl #16         @ r1<- HHHHhhhh (high word)
790    FETCH_ADVANCE_INST(5)               @ advance rPC, load rINST
791    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
792    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
793    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
794    GOTO_OPCODE(ip)                     @ jump to next instruction
795
796/* ------------------------------ */
797    .balign 64
798.L_OP_CONST_WIDE_HIGH16: /* 0x19 */
799/* File: armv5te/OP_CONST_WIDE_HIGH16.S */
800    /* const-wide/high16 vAA, #+BBBB000000000000 */
801    FETCH(r1, 1)                        @ r1<- 0000BBBB (zero-extended)
802    mov     r3, rINST, lsr #8           @ r3<- AA
803    mov     r0, #0                      @ r0<- 00000000
804    mov     r1, r1, lsl #16             @ r1<- BBBB0000
805    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
806    add     r3, rFP, r3, lsl #2         @ r3<- &fp[AA]
807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
808    stmia   r3, {r0-r1}                 @ vAA<- r0/r1
809    GOTO_OPCODE(ip)                     @ jump to next instruction
810
811/* ------------------------------ */
812    .balign 64
813.L_OP_CONST_STRING: /* 0x1a */
814/* File: armv5te/OP_CONST_STRING.S */
815    /* const/string vAA, String@BBBB */
816    FETCH(r1, 1)                        @ r1<- BBBB
817    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
818    mov     r9, rINST, lsr #8           @ r9<- AA
819    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
820    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
821    cmp     r0, #0                      @ not yet resolved?
822    beq     .LOP_CONST_STRING_resolve
823    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
825    SET_VREG(r0, r9)                    @ vAA<- r0
826    GOTO_OPCODE(ip)                     @ jump to next instruction
827
828/* ------------------------------ */
829    .balign 64
830.L_OP_CONST_STRING_JUMBO: /* 0x1b */
831/* File: armv5te/OP_CONST_STRING_JUMBO.S */
832    /* const/string vAA, String@BBBBBBBB */
833    FETCH(r0, 1)                        @ r0<- bbbb (low)
834    FETCH(r1, 2)                        @ r1<- BBBB (high)
835    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
836    mov     r9, rINST, lsr #8           @ r9<- AA
837    ldr     r2, [r2, #offDvmDex_pResStrings]   @ r2<- dvmDex->pResStrings
838    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
839    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResStrings[BBBB]
840    cmp     r0, #0
841    beq     .LOP_CONST_STRING_JUMBO_resolve
842    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
844    SET_VREG(r0, r9)                    @ vAA<- r0
845    GOTO_OPCODE(ip)                     @ jump to next instruction
846
847/* ------------------------------ */
848    .balign 64
849.L_OP_CONST_CLASS: /* 0x1c */
850/* File: armv5te/OP_CONST_CLASS.S */
851    /* const/class vAA, Class@BBBB */
852    FETCH(r1, 1)                        @ r1<- BBBB
853    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- glue->methodClassDex
854    mov     r9, rINST, lsr #8           @ r9<- AA
855    ldr     r2, [r2, #offDvmDex_pResClasses]   @ r2<- dvmDex->pResClasses
856    ldr     r0, [r2, r1, lsl #2]        @ r0<- pResClasses[BBBB]
857    cmp     r0, #0                      @ not yet resolved?
858    beq     .LOP_CONST_CLASS_resolve
859    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
861    SET_VREG(r0, r9)                    @ vAA<- r0
862    GOTO_OPCODE(ip)                     @ jump to next instruction
863
864/* ------------------------------ */
865    .balign 64
866.L_OP_MONITOR_ENTER: /* 0x1d */
867/* File: armv5te/OP_MONITOR_ENTER.S */
868    /*
869     * Synchronize on an object.
870     */
871    /* monitor-enter vAA */
872    mov     r2, rINST, lsr #8           @ r2<- AA
873    GET_VREG(r1, r2)                    @ r1<- vAA (object)
874    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
875    cmp     r1, #0                      @ null object?
876    EXPORT_PC()                         @ need for precise GC, MONITOR_TRACKING
877    beq     common_errNullObject        @ null object, throw an exception
878    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
879    bl      dvmLockObject               @ call(self, obj)
880#ifdef WITH_DEADLOCK_PREDICTION /* implies WITH_MONITOR_TRACKING */
881    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
882    ldr     r1, [r0, #offThread_exception] @ check for exception
883    cmp     r1, #0
884    bne     common_exceptionThrown      @ exception raised, bail out
885#endif
886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
887    GOTO_OPCODE(ip)                     @ jump to next instruction
888
889/* ------------------------------ */
890    .balign 64
891.L_OP_MONITOR_EXIT: /* 0x1e */
892/* File: armv5te/OP_MONITOR_EXIT.S */
893    /*
894     * Unlock an object.
895     *
896     * Exceptions that occur when unlocking a monitor need to appear as
897     * if they happened at the following instruction.  See the Dalvik
898     * instruction spec.
899     */
900    /* monitor-exit vAA */
901    mov     r2, rINST, lsr #8           @ r2<- AA
902    EXPORT_PC()                         @ before fetch: export the PC
903    GET_VREG(r1, r2)                    @ r1<- vAA (object)
904    cmp     r1, #0                      @ null object?
905    beq     1f                          @ yes
906    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
907    bl      dvmUnlockObject             @ r0<- success for unlock(self, obj)
908    cmp     r0, #0                      @ failed?
909    FETCH_ADVANCE_INST(1)               @ before throw: advance rPC, load rINST
910    beq     common_exceptionThrown      @ yes, exception is pending
911    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
912    GOTO_OPCODE(ip)                     @ jump to next instruction
9131:
914    FETCH_ADVANCE_INST(1)               @ advance before throw
915    b      common_errNullObject
916
917/* ------------------------------ */
918    .balign 64
919.L_OP_CHECK_CAST: /* 0x1f */
920/* File: armv5te/OP_CHECK_CAST.S */
921    /*
922     * Check to see if a cast from one class to another is allowed.
923     */
924    /* check-cast vAA, class@BBBB */
925    mov     r3, rINST, lsr #8           @ r3<- AA
926    FETCH(r2, 1)                        @ r2<- BBBB
927    GET_VREG(r9, r3)                    @ r9<- object
928    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- pDvmDex
929    cmp     r9, #0                      @ is object null?
930    ldr     r0, [r0, #offDvmDex_pResClasses]    @ r0<- pDvmDex->pResClasses
931    beq     .LOP_CHECK_CAST_okay            @ null obj, cast always succeeds
932    ldr     r1, [r0, r2, lsl #2]        @ r1<- resolved class
933    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
934    cmp     r1, #0                      @ have we resolved this before?
935    beq     .LOP_CHECK_CAST_resolve         @ not resolved, do it now
936.LOP_CHECK_CAST_resolved:
937    cmp     r0, r1                      @ same class (trivial success)?
938    bne     .LOP_CHECK_CAST_fullcheck       @ no, do full check
939.LOP_CHECK_CAST_okay:
940    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
941    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
942    GOTO_OPCODE(ip)                     @ jump to next instruction
943
944/* ------------------------------ */
945    .balign 64
946.L_OP_INSTANCE_OF: /* 0x20 */
947/* File: armv5te/OP_INSTANCE_OF.S */
948    /*
949     * Check to see if an object reference is an instance of a class.
950     *
951     * Most common situation is a non-null object, being compared against
952     * an already-resolved class.
953     */
954    /* instance-of vA, vB, class@CCCC */
955    mov     r3, rINST, lsr #12          @ r3<- B
956    mov     r9, rINST, lsr #8           @ r9<- A+
957    GET_VREG(r0, r3)                    @ r0<- vB (object)
958    and     r9, r9, #15                 @ r9<- A
959    cmp     r0, #0                      @ is object null?
960    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- pDvmDex
961    beq     .LOP_INSTANCE_OF_store           @ null obj, not an instance, store r0
962    FETCH(r3, 1)                        @ r3<- CCCC
963    ldr     r2, [r2, #offDvmDex_pResClasses]    @ r2<- pDvmDex->pResClasses
964    ldr     r1, [r2, r3, lsl #2]        @ r1<- resolved class
965    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
966    cmp     r1, #0                      @ have we resolved this before?
967    beq     .LOP_INSTANCE_OF_resolve         @ not resolved, do it now
968.LOP_INSTANCE_OF_resolved: @ r0=obj->clazz, r1=resolved class
969    cmp     r0, r1                      @ same class (trivial success)?
970    beq     .LOP_INSTANCE_OF_trivial         @ yes, trivial finish
971    b       .LOP_INSTANCE_OF_fullcheck       @ no, do full check
972
973/* ------------------------------ */
974    .balign 64
975.L_OP_ARRAY_LENGTH: /* 0x21 */
976/* File: armv5te/OP_ARRAY_LENGTH.S */
977    /*
978     * Return the length of an array.
979     */
980    mov     r1, rINST, lsr #12          @ r1<- B
981    mov     r2, rINST, lsr #8           @ r2<- A+
982    GET_VREG(r0, r1)                    @ r0<- vB (object ref)
983    and     r2, r2, #15                 @ r2<- A
984    cmp     r0, #0                      @ is object null?
985    beq     common_errNullObject        @ yup, fail
986    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
987    ldr     r3, [r0, #offArrayObject_length]    @ r3<- array length
988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
989    SET_VREG(r3, r2)                    @ vB<- length
990    GOTO_OPCODE(ip)                     @ jump to next instruction
991
992/* ------------------------------ */
993    .balign 64
994.L_OP_NEW_INSTANCE: /* 0x22 */
995/* File: armv5te/OP_NEW_INSTANCE.S */
996    /*
997     * Create a new instance of a class.
998     */
999    /* new-instance vAA, class@BBBB */
1000    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1001    FETCH(r1, 1)                        @ r1<- BBBB
1002    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1003    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1004    EXPORT_PC()                         @ req'd for init, resolve, alloc
1005    cmp     r0, #0                      @ already resolved?
1006    beq     .LOP_NEW_INSTANCE_resolve         @ no, resolve it now
1007.LOP_NEW_INSTANCE_resolved:   @ r0=class
1008    ldrb    r1, [r0, #offClassObject_status]    @ r1<- ClassStatus enum
1009    cmp     r1, #CLASS_INITIALIZED      @ has class been initialized?
1010    bne     .LOP_NEW_INSTANCE_needinit        @ no, init class now
1011.LOP_NEW_INSTANCE_initialized: @ r0=class
1012    mov     r1, #ALLOC_DONT_TRACK       @ flags for alloc call
1013    bl      dvmAllocObject              @ r0<- new object
1014    b       .LOP_NEW_INSTANCE_finish          @ continue
1015
1016/* ------------------------------ */
1017    .balign 64
1018.L_OP_NEW_ARRAY: /* 0x23 */
1019/* File: armv5te/OP_NEW_ARRAY.S */
1020    /*
1021     * Allocate an array of objects, specified with the array class
1022     * and a count.
1023     *
1024     * The verifier guarantees that this is an array class, so we don't
1025     * check for it here.
1026     */
1027    /* new-array vA, vB, class@CCCC */
1028    mov     r0, rINST, lsr #12          @ r0<- B
1029    FETCH(r2, 1)                        @ r2<- CCCC
1030    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1031    GET_VREG(r1, r0)                    @ r1<- vB (array length)
1032    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1033    cmp     r1, #0                      @ check length
1034    ldr     r0, [r3, r2, lsl #2]        @ r0<- resolved class
1035    bmi     common_errNegativeArraySize @ negative length, bail
1036    cmp     r0, #0                      @ already resolved?
1037    EXPORT_PC()                         @ req'd for resolve, alloc
1038    bne     .LOP_NEW_ARRAY_finish          @ resolved, continue
1039    b       .LOP_NEW_ARRAY_resolve         @ do resolve now
1040
1041/* ------------------------------ */
1042    .balign 64
1043.L_OP_FILLED_NEW_ARRAY: /* 0x24 */
1044/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1045    /*
1046     * Create a new array with elements filled from registers.
1047     *
1048     * for: filled-new-array, filled-new-array/range
1049     */
1050    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1051    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1052    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1053    FETCH(r1, 1)                        @ r1<- BBBB
1054    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1055    EXPORT_PC()                         @ need for resolve and alloc
1056    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1057    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1058    cmp     r0, #0                      @ already resolved?
1059    bne     .LOP_FILLED_NEW_ARRAY_continue        @ yes, continue on
10608:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1061    mov     r2, #0                      @ r2<- false
1062    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1063    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1064    cmp     r0, #0                      @ got null?
1065    beq     common_exceptionThrown      @ yes, handle exception
1066    b       .LOP_FILLED_NEW_ARRAY_continue
1067
1068/* ------------------------------ */
1069    .balign 64
1070.L_OP_FILLED_NEW_ARRAY_RANGE: /* 0x25 */
1071/* File: armv5te/OP_FILLED_NEW_ARRAY_RANGE.S */
1072/* File: armv5te/OP_FILLED_NEW_ARRAY.S */
1073    /*
1074     * Create a new array with elements filled from registers.
1075     *
1076     * for: filled-new-array, filled-new-array/range
1077     */
1078    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
1079    /* op {vCCCC..v(CCCC+AA-1)}, type@BBBB */
1080    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
1081    FETCH(r1, 1)                        @ r1<- BBBB
1082    ldr     r3, [r3, #offDvmDex_pResClasses]    @ r3<- pDvmDex->pResClasses
1083    EXPORT_PC()                         @ need for resolve and alloc
1084    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved class
1085    mov     r10, rINST, lsr #8          @ r10<- AA or BA
1086    cmp     r0, #0                      @ already resolved?
1087    bne     .LOP_FILLED_NEW_ARRAY_RANGE_continue        @ yes, continue on
10888:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
1089    mov     r2, #0                      @ r2<- false
1090    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
1091    bl      dvmResolveClass             @ r0<- call(clazz, ref)
1092    cmp     r0, #0                      @ got null?
1093    beq     common_exceptionThrown      @ yes, handle exception
1094    b       .LOP_FILLED_NEW_ARRAY_RANGE_continue
1095
1096
1097/* ------------------------------ */
1098    .balign 64
1099.L_OP_FILL_ARRAY_DATA: /* 0x26 */
1100/* File: armv5te/OP_FILL_ARRAY_DATA.S */
1101    /* fill-array-data vAA, +BBBBBBBB */
1102    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1103    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1104    mov     r3, rINST, lsr #8           @ r3<- AA
1105    orr     r1, r0, r1, lsl #16         @ r1<- BBBBbbbb
1106    GET_VREG(r0, r3)                    @ r0<- vAA (array object)
1107    add     r1, rPC, r1, lsl #1         @ r1<- PC + BBBBbbbb*2 (array data off.)
1108    EXPORT_PC();
1109    bl      dvmInterpHandleFillArrayData@ fill the array with predefined data
1110    cmp     r0, #0                      @ 0 means an exception is thrown
1111    beq     common_exceptionThrown      @ has exception
1112    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
1113    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1114    GOTO_OPCODE(ip)                     @ jump to next instruction
1115
1116/* ------------------------------ */
1117    .balign 64
1118.L_OP_THROW: /* 0x27 */
1119/* File: armv5te/OP_THROW.S */
1120    /*
1121     * Throw an exception object in the current thread.
1122     */
1123    /* throw vAA */
1124    mov     r2, rINST, lsr #8           @ r2<- AA
1125    GET_VREG(r1, r2)                    @ r1<- vAA (exception object)
1126    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
1127    EXPORT_PC()                         @ exception handler can throw
1128    cmp     r1, #0                      @ null object?
1129    beq     common_errNullObject        @ yes, throw an NPE instead
1130    @ bypass dvmSetException, just store it
1131    str     r1, [r0, #offThread_exception]  @ thread->exception<- obj
1132    b       common_exceptionThrown
1133
1134/* ------------------------------ */
1135    .balign 64
1136.L_OP_GOTO: /* 0x28 */
1137/* File: armv5te/OP_GOTO.S */
1138    /*
1139     * Unconditional branch, 8-bit offset.
1140     *
1141     * The branch distance is a signed code-unit offset, which we need to
1142     * double to get a byte offset.
1143     */
1144    /* goto +AA */
1145    mov     r0, rINST, lsl #16          @ r0<- AAxx0000
1146    movs    r9, r0, asr #24             @ r9<- ssssssAA (sign-extended)
1147    mov     r9, r9, lsl #1              @ r9<- byte offset
1148    bmi     common_backwardBranch       @ backward branch, do periodic checks
1149#if defined(WITH_JIT)
1150    GET_JIT_PROF_TABLE(r0)
1151    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1152    cmp     r0,#0
1153    bne     common_updateProfile
1154    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1155    GOTO_OPCODE(ip)                     @ jump to next instruction
1156#else
1157    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1159    GOTO_OPCODE(ip)                     @ jump to next instruction
1160#endif
1161
1162/* ------------------------------ */
1163    .balign 64
1164.L_OP_GOTO_16: /* 0x29 */
1165/* File: armv5te/OP_GOTO_16.S */
1166    /*
1167     * Unconditional branch, 16-bit offset.
1168     *
1169     * The branch distance is a signed code-unit offset, which we need to
1170     * double to get a byte offset.
1171     */
1172    /* goto/16 +AAAA */
1173    FETCH_S(r0, 1)                      @ r0<- ssssAAAA (sign-extended)
1174    movs    r9, r0, asl #1              @ r9<- byte offset, check sign
1175    bmi     common_backwardBranch       @ backward branch, do periodic checks
1176#if defined(WITH_JIT)
1177    GET_JIT_PROF_TABLE(r0)
1178    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1179    cmp     r0,#0
1180    bne     common_updateProfile
1181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1182    GOTO_OPCODE(ip)                     @ jump to next instruction
1183#else
1184    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1185    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1186    GOTO_OPCODE(ip)                     @ jump to next instruction
1187#endif
1188
1189/* ------------------------------ */
1190    .balign 64
1191.L_OP_GOTO_32: /* 0x2a */
1192/* File: armv5te/OP_GOTO_32.S */
1193    /*
1194     * Unconditional branch, 32-bit offset.
1195     *
1196     * The branch distance is a signed code-unit offset, which we need to
1197     * double to get a byte offset.
1198     *
1199     * Unlike most opcodes, this one is allowed to branch to itself, so
1200     * our "backward branch" test must be "<=0" instead of "<0".  The ORRS
1201     * instruction doesn't affect the V flag, so we need to clear it
1202     * explicitly.
1203     */
1204    /* goto/32 +AAAAAAAA */
1205    FETCH(r0, 1)                        @ r0<- aaaa (lo)
1206    FETCH(r1, 2)                        @ r1<- AAAA (hi)
1207    cmp     ip, ip                      @ (clear V flag during stall)
1208    orrs    r0, r0, r1, lsl #16         @ r0<- AAAAaaaa, check sign
1209    mov     r9, r0, asl #1              @ r9<- byte offset
1210    ble     common_backwardBranch       @ backward branch, do periodic checks
1211#if defined(WITH_JIT)
1212    GET_JIT_PROF_TABLE(r0)
1213    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1214    cmp     r0,#0
1215    bne     common_updateProfile
1216    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1217    GOTO_OPCODE(ip)                     @ jump to next instruction
1218#else
1219    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1221    GOTO_OPCODE(ip)                     @ jump to next instruction
1222#endif
1223
1224/* ------------------------------ */
1225    .balign 64
1226.L_OP_PACKED_SWITCH: /* 0x2b */
1227/* File: armv5te/OP_PACKED_SWITCH.S */
1228    /*
1229     * Handle a packed-switch or sparse-switch instruction.  In both cases
1230     * we decode it and hand it off to a helper function.
1231     *
1232     * We don't really expect backward branches in a switch statement, but
1233     * they're perfectly legal, so we check for them here.
1234     *
1235     * for: packed-switch, sparse-switch
1236     */
1237    /* op vAA, +BBBB */
1238    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1239    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1240    mov     r3, rINST, lsr #8           @ r3<- AA
1241    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1242    GET_VREG(r1, r3)                    @ r1<- vAA
1243    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1244    bl      dvmInterpHandlePackedSwitch                       @ r0<- code-unit branch offset
1245    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1246    bmi     common_backwardBranch       @ backward branch, do periodic checks
1247    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1248#if defined(WITH_JIT)
1249    GET_JIT_PROF_TABLE(r0)
1250    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1251    cmp     r0,#0
1252    bne     common_updateProfile
1253    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1254    GOTO_OPCODE(ip)                     @ jump to next instruction
1255#else
1256    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1258    GOTO_OPCODE(ip)                     @ jump to next instruction
1259#endif
1260
1261/* ------------------------------ */
1262    .balign 64
1263.L_OP_SPARSE_SWITCH: /* 0x2c */
1264/* File: armv5te/OP_SPARSE_SWITCH.S */
1265/* File: armv5te/OP_PACKED_SWITCH.S */
1266    /*
1267     * Handle a packed-switch or sparse-switch instruction.  In both cases
1268     * we decode it and hand it off to a helper function.
1269     *
1270     * We don't really expect backward branches in a switch statement, but
1271     * they're perfectly legal, so we check for them here.
1272     *
1273     * for: packed-switch, sparse-switch
1274     */
1275    /* op vAA, +BBBB */
1276    FETCH(r0, 1)                        @ r0<- bbbb (lo)
1277    FETCH(r1, 2)                        @ r1<- BBBB (hi)
1278    mov     r3, rINST, lsr #8           @ r3<- AA
1279    orr     r0, r0, r1, lsl #16         @ r0<- BBBBbbbb
1280    GET_VREG(r1, r3)                    @ r1<- vAA
1281    add     r0, rPC, r0, lsl #1         @ r0<- PC + BBBBbbbb*2
1282    bl      dvmInterpHandleSparseSwitch                       @ r0<- code-unit branch offset
1283    movs    r9, r0, asl #1              @ r9<- branch byte offset, check sign
1284    bmi     common_backwardBranch       @ backward branch, do periodic checks
1285    beq     common_backwardBranch       @ (want to use BLE but V is unknown)
1286#if defined(WITH_JIT)
1287    GET_JIT_PROF_TABLE(r0)
1288    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1289    cmp     r0,#0
1290    bne     common_updateProfile
1291    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1292    GOTO_OPCODE(ip)                     @ jump to next instruction
1293#else
1294    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1295    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1296    GOTO_OPCODE(ip)                     @ jump to next instruction
1297#endif
1298
1299
1300/* ------------------------------ */
1301    .balign 64
1302.L_OP_CMPL_FLOAT: /* 0x2d */
1303/* File: arm-vfp/OP_CMPL_FLOAT.S */
1304    /*
1305     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1306     * destination register based on the results of the comparison.
1307     *
1308     * int compare(x, y) {
1309     *     if (x == y) {
1310     *         return 0;
1311     *     } else if (x > y) {
1312     *         return 1;
1313     *     } else if (x < y) {
1314     *         return -1;
1315     *     } else {
1316     *         return -1;
1317     *     }
1318     * }
1319     */
1320    /* op vAA, vBB, vCC */
1321    FETCH(r0, 1)                        @ r0<- CCBB
1322    mov     r9, rINST, lsr #8           @ r9<- AA
1323    and     r2, r0, #255                @ r2<- BB
1324    mov     r3, r0, lsr #8              @ r3<- CC
1325    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1326    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1327    flds    s0, [r2]                    @ s0<- vBB
1328    flds    s1, [r3]                    @ s1<- vCC
1329    fcmpes  s0, s1                      @ compare (vBB, vCC)
1330    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1331    mvn     r0, #0                      @ r0<- -1 (default)
1332    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1333    fmstat                              @ export status flags
1334    movgt   r0, #1                      @ (greater than) r1<- 1
1335    moveq   r0, #0                      @ (equal) r1<- 0
1336    b       .LOP_CMPL_FLOAT_finish          @ argh
1337
1338
1339/* ------------------------------ */
1340    .balign 64
1341.L_OP_CMPG_FLOAT: /* 0x2e */
1342/* File: arm-vfp/OP_CMPG_FLOAT.S */
1343    /*
1344     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1345     * destination register based on the results of the comparison.
1346     *
1347     * int compare(x, y) {
1348     *     if (x == y) {
1349     *         return 0;
1350     *     } else if (x < y) {
1351     *         return -1;
1352     *     } else if (x > y) {
1353     *         return 1;
1354     *     } else {
1355     *         return 1;
1356     *     }
1357     * }
1358     */
1359    /* op vAA, vBB, vCC */
1360    FETCH(r0, 1)                        @ r0<- CCBB
1361    mov     r9, rINST, lsr #8           @ r9<- AA
1362    and     r2, r0, #255                @ r2<- BB
1363    mov     r3, r0, lsr #8              @ r3<- CC
1364    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1365    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1366    flds    s0, [r2]                    @ s0<- vBB
1367    flds    s1, [r3]                    @ s1<- vCC
1368    fcmpes  s0, s1                      @ compare (vBB, vCC)
1369    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1370    mov     r0, #1                      @ r0<- 1 (default)
1371    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1372    fmstat                              @ export status flags
1373    mvnmi   r0, #0                      @ (less than) r1<- -1
1374    moveq   r0, #0                      @ (equal) r1<- 0
1375    b       .LOP_CMPG_FLOAT_finish          @ argh
1376
1377
1378/* ------------------------------ */
1379    .balign 64
1380.L_OP_CMPL_DOUBLE: /* 0x2f */
1381/* File: arm-vfp/OP_CMPL_DOUBLE.S */
1382    /*
1383     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1384     * destination register based on the results of the comparison.
1385     *
1386     * int compare(x, y) {
1387     *     if (x == y) {
1388     *         return 0;
1389     *     } else if (x > y) {
1390     *         return 1;
1391     *     } else if (x < y) {
1392     *         return -1;
1393     *     } else {
1394     *         return -1;
1395     *     }
1396     * }
1397     */
1398    /* op vAA, vBB, vCC */
1399    FETCH(r0, 1)                        @ r0<- CCBB
1400    mov     r9, rINST, lsr #8           @ r9<- AA
1401    and     r2, r0, #255                @ r2<- BB
1402    mov     r3, r0, lsr #8              @ r3<- CC
1403    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1404    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1405    fldd    d0, [r2]                    @ d0<- vBB
1406    fldd    d1, [r3]                    @ d1<- vCC
1407    fcmped  d0, d1                      @ compare (vBB, vCC)
1408    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1409    mvn     r0, #0                      @ r0<- -1 (default)
1410    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1411    fmstat                              @ export status flags
1412    movgt   r0, #1                      @ (greater than) r1<- 1
1413    moveq   r0, #0                      @ (equal) r1<- 0
1414    b       .LOP_CMPL_DOUBLE_finish          @ argh
1415
1416
1417/* ------------------------------ */
1418    .balign 64
1419.L_OP_CMPG_DOUBLE: /* 0x30 */
1420/* File: arm-vfp/OP_CMPG_DOUBLE.S */
1421    /*
1422     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1423     * destination register based on the results of the comparison.
1424     *
1425     * int compare(x, y) {
1426     *     if (x == y) {
1427     *         return 0;
1428     *     } else if (x < y) {
1429     *         return -1;
1430     *     } else if (x > y) {
1431     *         return 1;
1432     *     } else {
1433     *         return 1;
1434     *     }
1435     * }
1436     */
1437    /* op vAA, vBB, vCC */
1438    FETCH(r0, 1)                        @ r0<- CCBB
1439    mov     r9, rINST, lsr #8           @ r9<- AA
1440    and     r2, r0, #255                @ r2<- BB
1441    mov     r3, r0, lsr #8              @ r3<- CC
1442    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
1443    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
1444    fldd    d0, [r2]                    @ d0<- vBB
1445    fldd    d1, [r3]                    @ d1<- vCC
1446    fcmped  d0, d1                      @ compare (vBB, vCC)
1447    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1448    mov     r0, #1                      @ r0<- 1 (default)
1449    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1450    fmstat                              @ export status flags
1451    mvnmi   r0, #0                      @ (less than) r1<- -1
1452    moveq   r0, #0                      @ (equal) r1<- 0
1453    b       .LOP_CMPG_DOUBLE_finish          @ argh
1454
1455
1456/* ------------------------------ */
1457    .balign 64
1458.L_OP_CMP_LONG: /* 0x31 */
1459/* File: armv5te/OP_CMP_LONG.S */
1460    /*
1461     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1462     * register based on the results of the comparison.
1463     *
1464     * We load the full values with LDM, but in practice many values could
1465     * be resolved by only looking at the high word.  This could be made
1466     * faster or slower by splitting the LDM into a pair of LDRs.
1467     *
1468     * If we just wanted to set condition flags, we could do this:
1469     *  subs    ip, r0, r2
1470     *  sbcs    ip, r1, r3
1471     *  subeqs  ip, r0, r2
1472     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1473     * integer value, which we can do with 2 conditional mov/mvn instructions
1474     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1475     * us a constant 5-cycle path plus a branch at the end to the
1476     * instruction epilogue code.  The multi-compare approach below needs
1477     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1478     * in the worst case (the 64-bit values are equal).
1479     */
1480    /* cmp-long vAA, vBB, vCC */
1481    FETCH(r0, 1)                        @ r0<- CCBB
1482    mov     r9, rINST, lsr #8           @ r9<- AA
1483    and     r2, r0, #255                @ r2<- BB
1484    mov     r3, r0, lsr #8              @ r3<- CC
1485    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1486    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1487    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1488    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1489    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1490    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1491    bgt     .LOP_CMP_LONG_greater
1492    subs    r1, r0, r2                  @ r1<- r0 - r2
1493    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1494    bne     .LOP_CMP_LONG_less
1495    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1496
1497/* ------------------------------ */
1498    .balign 64
1499.L_OP_IF_EQ: /* 0x32 */
1500/* File: armv5te/OP_IF_EQ.S */
1501/* File: armv5te/bincmp.S */
1502    /*
1503     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1504     * fragment that specifies the *reverse* comparison to perform, e.g.
1505     * for "if-le" you would use "gt".
1506     *
1507     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1508     */
1509    /* if-cmp vA, vB, +CCCC */
1510    mov     r0, rINST, lsr #8           @ r0<- A+
1511    mov     r1, rINST, lsr #12          @ r1<- B
1512    and     r0, r0, #15
1513    GET_VREG(r3, r1)                    @ r3<- vB
1514    GET_VREG(r2, r0)                    @ r2<- vA
1515    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1516    cmp     r2, r3                      @ compare (vA, vB)
1517    bne  1f                      @ branch to 1 if comparison failed
1518    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1519    movs    r9, r9, asl #1              @ convert to bytes, check sign
1520    bmi     common_backwardBranch       @ yes, do periodic checks
15211:
1522#if defined(WITH_JIT)
1523    GET_JIT_PROF_TABLE(r0)
1524    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1525    b        common_testUpdateProfile
1526#else
1527    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1528    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1529    GOTO_OPCODE(ip)                     @ jump to next instruction
1530#endif
1531
1532
1533/* ------------------------------ */
1534    .balign 64
1535.L_OP_IF_NE: /* 0x33 */
1536/* File: armv5te/OP_IF_NE.S */
1537/* File: armv5te/bincmp.S */
1538    /*
1539     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1540     * fragment that specifies the *reverse* comparison to perform, e.g.
1541     * for "if-le" you would use "gt".
1542     *
1543     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1544     */
1545    /* if-cmp vA, vB, +CCCC */
1546    mov     r0, rINST, lsr #8           @ r0<- A+
1547    mov     r1, rINST, lsr #12          @ r1<- B
1548    and     r0, r0, #15
1549    GET_VREG(r3, r1)                    @ r3<- vB
1550    GET_VREG(r2, r0)                    @ r2<- vA
1551    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1552    cmp     r2, r3                      @ compare (vA, vB)
1553    beq  1f                      @ branch to 1 if comparison failed
1554    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1555    movs    r9, r9, asl #1              @ convert to bytes, check sign
1556    bmi     common_backwardBranch       @ yes, do periodic checks
15571:
1558#if defined(WITH_JIT)
1559    GET_JIT_PROF_TABLE(r0)
1560    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1561    b        common_testUpdateProfile
1562#else
1563    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1564    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1565    GOTO_OPCODE(ip)                     @ jump to next instruction
1566#endif
1567
1568
1569/* ------------------------------ */
1570    .balign 64
1571.L_OP_IF_LT: /* 0x34 */
1572/* File: armv5te/OP_IF_LT.S */
1573/* File: armv5te/bincmp.S */
1574    /*
1575     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1576     * fragment that specifies the *reverse* comparison to perform, e.g.
1577     * for "if-le" you would use "gt".
1578     *
1579     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1580     */
1581    /* if-cmp vA, vB, +CCCC */
1582    mov     r0, rINST, lsr #8           @ r0<- A+
1583    mov     r1, rINST, lsr #12          @ r1<- B
1584    and     r0, r0, #15
1585    GET_VREG(r3, r1)                    @ r3<- vB
1586    GET_VREG(r2, r0)                    @ r2<- vA
1587    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1588    cmp     r2, r3                      @ compare (vA, vB)
1589    bge  1f                      @ branch to 1 if comparison failed
1590    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1591    movs    r9, r9, asl #1              @ convert to bytes, check sign
1592    bmi     common_backwardBranch       @ yes, do periodic checks
15931:
1594#if defined(WITH_JIT)
1595    GET_JIT_PROF_TABLE(r0)
1596    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1597    b        common_testUpdateProfile
1598#else
1599    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1600    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1601    GOTO_OPCODE(ip)                     @ jump to next instruction
1602#endif
1603
1604
1605/* ------------------------------ */
1606    .balign 64
1607.L_OP_IF_GE: /* 0x35 */
1608/* File: armv5te/OP_IF_GE.S */
1609/* File: armv5te/bincmp.S */
1610    /*
1611     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1612     * fragment that specifies the *reverse* comparison to perform, e.g.
1613     * for "if-le" you would use "gt".
1614     *
1615     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1616     */
1617    /* if-cmp vA, vB, +CCCC */
1618    mov     r0, rINST, lsr #8           @ r0<- A+
1619    mov     r1, rINST, lsr #12          @ r1<- B
1620    and     r0, r0, #15
1621    GET_VREG(r3, r1)                    @ r3<- vB
1622    GET_VREG(r2, r0)                    @ r2<- vA
1623    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1624    cmp     r2, r3                      @ compare (vA, vB)
1625    blt  1f                      @ branch to 1 if comparison failed
1626    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1627    movs    r9, r9, asl #1              @ convert to bytes, check sign
1628    bmi     common_backwardBranch       @ yes, do periodic checks
16291:
1630#if defined(WITH_JIT)
1631    GET_JIT_PROF_TABLE(r0)
1632    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1633    b        common_testUpdateProfile
1634#else
1635    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1636    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1637    GOTO_OPCODE(ip)                     @ jump to next instruction
1638#endif
1639
1640
1641/* ------------------------------ */
1642    .balign 64
1643.L_OP_IF_GT: /* 0x36 */
1644/* File: armv5te/OP_IF_GT.S */
1645/* File: armv5te/bincmp.S */
1646    /*
1647     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1648     * fragment that specifies the *reverse* comparison to perform, e.g.
1649     * for "if-le" you would use "gt".
1650     *
1651     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1652     */
1653    /* if-cmp vA, vB, +CCCC */
1654    mov     r0, rINST, lsr #8           @ r0<- A+
1655    mov     r1, rINST, lsr #12          @ r1<- B
1656    and     r0, r0, #15
1657    GET_VREG(r3, r1)                    @ r3<- vB
1658    GET_VREG(r2, r0)                    @ r2<- vA
1659    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1660    cmp     r2, r3                      @ compare (vA, vB)
1661    ble  1f                      @ branch to 1 if comparison failed
1662    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1663    movs    r9, r9, asl #1              @ convert to bytes, check sign
1664    bmi     common_backwardBranch       @ yes, do periodic checks
16651:
1666#if defined(WITH_JIT)
1667    GET_JIT_PROF_TABLE(r0)
1668    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1669    b        common_testUpdateProfile
1670#else
1671    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1672    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1673    GOTO_OPCODE(ip)                     @ jump to next instruction
1674#endif
1675
1676
1677/* ------------------------------ */
1678    .balign 64
1679.L_OP_IF_LE: /* 0x37 */
1680/* File: armv5te/OP_IF_LE.S */
1681/* File: armv5te/bincmp.S */
1682    /*
1683     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1684     * fragment that specifies the *reverse* comparison to perform, e.g.
1685     * for "if-le" you would use "gt".
1686     *
1687     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1688     */
1689    /* if-cmp vA, vB, +CCCC */
1690    mov     r0, rINST, lsr #8           @ r0<- A+
1691    mov     r1, rINST, lsr #12          @ r1<- B
1692    and     r0, r0, #15
1693    GET_VREG(r3, r1)                    @ r3<- vB
1694    GET_VREG(r2, r0)                    @ r2<- vA
1695    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1696    cmp     r2, r3                      @ compare (vA, vB)
1697    bgt  1f                      @ branch to 1 if comparison failed
1698    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1699    movs    r9, r9, asl #1              @ convert to bytes, check sign
1700    bmi     common_backwardBranch       @ yes, do periodic checks
17011:
1702#if defined(WITH_JIT)
1703    GET_JIT_PROF_TABLE(r0)
1704    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1705    b        common_testUpdateProfile
1706#else
1707    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1708    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1709    GOTO_OPCODE(ip)                     @ jump to next instruction
1710#endif
1711
1712
1713/* ------------------------------ */
1714    .balign 64
1715.L_OP_IF_EQZ: /* 0x38 */
1716/* File: armv5te/OP_IF_EQZ.S */
1717/* File: armv5te/zcmp.S */
1718    /*
1719     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1720     * fragment that specifies the *reverse* comparison to perform, e.g.
1721     * for "if-le" you would use "gt".
1722     *
1723     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1724     */
1725    /* if-cmp vAA, +BBBB */
1726    mov     r0, rINST, lsr #8           @ r0<- AA
1727    GET_VREG(r2, r0)                    @ r2<- vAA
1728    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1729    cmp     r2, #0                      @ compare (vA, 0)
1730    bne  1f                      @ branch to 1 if comparison failed
1731    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1732    movs    r9, r9, asl #1              @ convert to bytes, check sign
1733    bmi     common_backwardBranch       @ backward branch, do periodic checks
17341:
1735#if defined(WITH_JIT)
1736    GET_JIT_PROF_TABLE(r0)
1737    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1738    cmp     r0,#0
1739    bne     common_updateProfile
1740    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1741    GOTO_OPCODE(ip)                     @ jump to next instruction
1742#else
1743    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1744    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1745    GOTO_OPCODE(ip)                     @ jump to next instruction
1746#endif
1747
1748
1749/* ------------------------------ */
1750    .balign 64
1751.L_OP_IF_NEZ: /* 0x39 */
1752/* File: armv5te/OP_IF_NEZ.S */
1753/* File: armv5te/zcmp.S */
1754    /*
1755     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1756     * fragment that specifies the *reverse* comparison to perform, e.g.
1757     * for "if-le" you would use "gt".
1758     *
1759     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1760     */
1761    /* if-cmp vAA, +BBBB */
1762    mov     r0, rINST, lsr #8           @ r0<- AA
1763    GET_VREG(r2, r0)                    @ r2<- vAA
1764    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1765    cmp     r2, #0                      @ compare (vA, 0)
1766    beq  1f                      @ branch to 1 if comparison failed
1767    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1768    movs    r9, r9, asl #1              @ convert to bytes, check sign
1769    bmi     common_backwardBranch       @ backward branch, do periodic checks
17701:
1771#if defined(WITH_JIT)
1772    GET_JIT_PROF_TABLE(r0)
1773    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1774    cmp     r0,#0
1775    bne     common_updateProfile
1776    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1777    GOTO_OPCODE(ip)                     @ jump to next instruction
1778#else
1779    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1780    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1781    GOTO_OPCODE(ip)                     @ jump to next instruction
1782#endif
1783
1784
1785/* ------------------------------ */
1786    .balign 64
1787.L_OP_IF_LTZ: /* 0x3a */
1788/* File: armv5te/OP_IF_LTZ.S */
1789/* File: armv5te/zcmp.S */
1790    /*
1791     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1792     * fragment that specifies the *reverse* comparison to perform, e.g.
1793     * for "if-le" you would use "gt".
1794     *
1795     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1796     */
1797    /* if-cmp vAA, +BBBB */
1798    mov     r0, rINST, lsr #8           @ r0<- AA
1799    GET_VREG(r2, r0)                    @ r2<- vAA
1800    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1801    cmp     r2, #0                      @ compare (vA, 0)
1802    bge  1f                      @ branch to 1 if comparison failed
1803    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1804    movs    r9, r9, asl #1              @ convert to bytes, check sign
1805    bmi     common_backwardBranch       @ backward branch, do periodic checks
18061:
1807#if defined(WITH_JIT)
1808    GET_JIT_PROF_TABLE(r0)
1809    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1810    cmp     r0,#0
1811    bne     common_updateProfile
1812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1813    GOTO_OPCODE(ip)                     @ jump to next instruction
1814#else
1815    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1817    GOTO_OPCODE(ip)                     @ jump to next instruction
1818#endif
1819
1820
1821/* ------------------------------ */
1822    .balign 64
1823.L_OP_IF_GEZ: /* 0x3b */
1824/* File: armv5te/OP_IF_GEZ.S */
1825/* File: armv5te/zcmp.S */
1826    /*
1827     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1828     * fragment that specifies the *reverse* comparison to perform, e.g.
1829     * for "if-le" you would use "gt".
1830     *
1831     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1832     */
1833    /* if-cmp vAA, +BBBB */
1834    mov     r0, rINST, lsr #8           @ r0<- AA
1835    GET_VREG(r2, r0)                    @ r2<- vAA
1836    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1837    cmp     r2, #0                      @ compare (vA, 0)
1838    blt  1f                      @ branch to 1 if comparison failed
1839    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1840    movs    r9, r9, asl #1              @ convert to bytes, check sign
1841    bmi     common_backwardBranch       @ backward branch, do periodic checks
18421:
1843#if defined(WITH_JIT)
1844    GET_JIT_PROF_TABLE(r0)
1845    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1846    cmp     r0,#0
1847    bne     common_updateProfile
1848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1849    GOTO_OPCODE(ip)                     @ jump to next instruction
1850#else
1851    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1852    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1853    GOTO_OPCODE(ip)                     @ jump to next instruction
1854#endif
1855
1856
1857/* ------------------------------ */
1858    .balign 64
1859.L_OP_IF_GTZ: /* 0x3c */
1860/* File: armv5te/OP_IF_GTZ.S */
1861/* File: armv5te/zcmp.S */
1862    /*
1863     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1864     * fragment that specifies the *reverse* comparison to perform, e.g.
1865     * for "if-le" you would use "gt".
1866     *
1867     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1868     */
1869    /* if-cmp vAA, +BBBB */
1870    mov     r0, rINST, lsr #8           @ r0<- AA
1871    GET_VREG(r2, r0)                    @ r2<- vAA
1872    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1873    cmp     r2, #0                      @ compare (vA, 0)
1874    ble  1f                      @ branch to 1 if comparison failed
1875    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1876    movs    r9, r9, asl #1              @ convert to bytes, check sign
1877    bmi     common_backwardBranch       @ backward branch, do periodic checks
18781:
1879#if defined(WITH_JIT)
1880    GET_JIT_PROF_TABLE(r0)
1881    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1882    cmp     r0,#0
1883    bne     common_updateProfile
1884    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1885    GOTO_OPCODE(ip)                     @ jump to next instruction
1886#else
1887    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1888    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1889    GOTO_OPCODE(ip)                     @ jump to next instruction
1890#endif
1891
1892
1893/* ------------------------------ */
1894    .balign 64
1895.L_OP_IF_LEZ: /* 0x3d */
1896/* File: armv5te/OP_IF_LEZ.S */
1897/* File: armv5te/zcmp.S */
1898    /*
1899     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1900     * fragment that specifies the *reverse* comparison to perform, e.g.
1901     * for "if-le" you would use "gt".
1902     *
1903     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1904     */
1905    /* if-cmp vAA, +BBBB */
1906    mov     r0, rINST, lsr #8           @ r0<- AA
1907    GET_VREG(r2, r0)                    @ r2<- vAA
1908    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1909    cmp     r2, #0                      @ compare (vA, 0)
1910    bgt  1f                      @ branch to 1 if comparison failed
1911    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1912    movs    r9, r9, asl #1              @ convert to bytes, check sign
1913    bmi     common_backwardBranch       @ backward branch, do periodic checks
19141:
1915#if defined(WITH_JIT)
1916    GET_JIT_PROF_TABLE(r0)
1917    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1918    cmp     r0,#0
1919    bne     common_updateProfile
1920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1921    GOTO_OPCODE(ip)                     @ jump to next instruction
1922#else
1923    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1925    GOTO_OPCODE(ip)                     @ jump to next instruction
1926#endif
1927
1928
1929/* ------------------------------ */
1930    .balign 64
1931.L_OP_UNUSED_3E: /* 0x3e */
1932/* File: armv5te/OP_UNUSED_3E.S */
1933/* File: armv5te/unused.S */
1934    bl      common_abort
1935
1936
1937/* ------------------------------ */
1938    .balign 64
1939.L_OP_UNUSED_3F: /* 0x3f */
1940/* File: armv5te/OP_UNUSED_3F.S */
1941/* File: armv5te/unused.S */
1942    bl      common_abort
1943
1944
1945/* ------------------------------ */
1946    .balign 64
1947.L_OP_UNUSED_40: /* 0x40 */
1948/* File: armv5te/OP_UNUSED_40.S */
1949/* File: armv5te/unused.S */
1950    bl      common_abort
1951
1952
1953/* ------------------------------ */
1954    .balign 64
1955.L_OP_UNUSED_41: /* 0x41 */
1956/* File: armv5te/OP_UNUSED_41.S */
1957/* File: armv5te/unused.S */
1958    bl      common_abort
1959
1960
1961/* ------------------------------ */
1962    .balign 64
1963.L_OP_UNUSED_42: /* 0x42 */
1964/* File: armv5te/OP_UNUSED_42.S */
1965/* File: armv5te/unused.S */
1966    bl      common_abort
1967
1968
1969/* ------------------------------ */
1970    .balign 64
1971.L_OP_UNUSED_43: /* 0x43 */
1972/* File: armv5te/OP_UNUSED_43.S */
1973/* File: armv5te/unused.S */
1974    bl      common_abort
1975
1976
1977/* ------------------------------ */
1978    .balign 64
1979.L_OP_AGET: /* 0x44 */
1980/* File: armv5te/OP_AGET.S */
1981    /*
1982     * Array get, 32 bits or less.  vAA <- vBB[vCC].
1983     *
1984     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
1985     * instructions.  We use a pair of FETCH_Bs instead.
1986     *
1987     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
1988     */
1989    /* op vAA, vBB, vCC */
1990    FETCH_B(r2, 1, 0)                   @ r2<- BB
1991    mov     r9, rINST, lsr #8           @ r9<- AA
1992    FETCH_B(r3, 1, 1)                   @ r3<- CC
1993    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
1994    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
1995    cmp     r0, #0                      @ null array object?
1996    beq     common_errNullObject        @ yes, bail
1997    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
1998    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
1999    cmp     r1, r3                      @ compare unsigned index, length
2000    bcs     common_errArrayIndex        @ index >= length, bail
2001    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2002    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2003    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2004    SET_VREG(r2, r9)                    @ vAA<- r2
2005    GOTO_OPCODE(ip)                     @ jump to next instruction
2006
2007/* ------------------------------ */
2008    .balign 64
2009.L_OP_AGET_WIDE: /* 0x45 */
2010/* File: armv5te/OP_AGET_WIDE.S */
2011    /*
2012     * Array get, 64 bits.  vAA <- vBB[vCC].
2013     *
2014     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2015     */
2016    /* aget-wide vAA, vBB, vCC */
2017    FETCH(r0, 1)                        @ r0<- CCBB
2018    mov     r9, rINST, lsr #8           @ r9<- AA
2019    and     r2, r0, #255                @ r2<- BB
2020    mov     r3, r0, lsr #8              @ r3<- CC
2021    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2022    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2023    cmp     r0, #0                      @ null array object?
2024    beq     common_errNullObject        @ yes, bail
2025    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2026    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2027    cmp     r1, r3                      @ compare unsigned index, length
2028    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2029    b       common_errArrayIndex        @ index >= length, bail
2030    @ May want to swap the order of these two branches depending on how the
2031    @ branch prediction (if any) handles conditional forward branches vs.
2032    @ unconditional forward branches.
2033
2034/* ------------------------------ */
2035    .balign 64
2036.L_OP_AGET_OBJECT: /* 0x46 */
2037/* File: armv5te/OP_AGET_OBJECT.S */
2038/* File: armv5te/OP_AGET.S */
2039    /*
2040     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2041     *
2042     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2043     * instructions.  We use a pair of FETCH_Bs instead.
2044     *
2045     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2046     */
2047    /* op vAA, vBB, vCC */
2048    FETCH_B(r2, 1, 0)                   @ r2<- BB
2049    mov     r9, rINST, lsr #8           @ r9<- AA
2050    FETCH_B(r3, 1, 1)                   @ r3<- CC
2051    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2052    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2053    cmp     r0, #0                      @ null array object?
2054    beq     common_errNullObject        @ yes, bail
2055    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2056    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2057    cmp     r1, r3                      @ compare unsigned index, length
2058    bcs     common_errArrayIndex        @ index >= length, bail
2059    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2060    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2061    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2062    SET_VREG(r2, r9)                    @ vAA<- r2
2063    GOTO_OPCODE(ip)                     @ jump to next instruction
2064
2065
2066/* ------------------------------ */
2067    .balign 64
2068.L_OP_AGET_BOOLEAN: /* 0x47 */
2069/* File: armv5te/OP_AGET_BOOLEAN.S */
2070/* File: armv5te/OP_AGET.S */
2071    /*
2072     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2073     *
2074     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2075     * instructions.  We use a pair of FETCH_Bs instead.
2076     *
2077     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2078     */
2079    /* op vAA, vBB, vCC */
2080    FETCH_B(r2, 1, 0)                   @ r2<- BB
2081    mov     r9, rINST, lsr #8           @ r9<- AA
2082    FETCH_B(r3, 1, 1)                   @ r3<- CC
2083    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2084    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2085    cmp     r0, #0                      @ null array object?
2086    beq     common_errNullObject        @ yes, bail
2087    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2088    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2089    cmp     r1, r3                      @ compare unsigned index, length
2090    bcs     common_errArrayIndex        @ index >= length, bail
2091    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2092    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2093    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2094    SET_VREG(r2, r9)                    @ vAA<- r2
2095    GOTO_OPCODE(ip)                     @ jump to next instruction
2096
2097
2098/* ------------------------------ */
2099    .balign 64
2100.L_OP_AGET_BYTE: /* 0x48 */
2101/* File: armv5te/OP_AGET_BYTE.S */
2102/* File: armv5te/OP_AGET.S */
2103    /*
2104     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2105     *
2106     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2107     * instructions.  We use a pair of FETCH_Bs instead.
2108     *
2109     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2110     */
2111    /* op vAA, vBB, vCC */
2112    FETCH_B(r2, 1, 0)                   @ r2<- BB
2113    mov     r9, rINST, lsr #8           @ r9<- AA
2114    FETCH_B(r3, 1, 1)                   @ r3<- CC
2115    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2116    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2117    cmp     r0, #0                      @ null array object?
2118    beq     common_errNullObject        @ yes, bail
2119    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2120    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2121    cmp     r1, r3                      @ compare unsigned index, length
2122    bcs     common_errArrayIndex        @ index >= length, bail
2123    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2124    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2125    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2126    SET_VREG(r2, r9)                    @ vAA<- r2
2127    GOTO_OPCODE(ip)                     @ jump to next instruction
2128
2129
2130/* ------------------------------ */
2131    .balign 64
2132.L_OP_AGET_CHAR: /* 0x49 */
2133/* File: armv5te/OP_AGET_CHAR.S */
2134/* File: armv5te/OP_AGET.S */
2135    /*
2136     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2137     *
2138     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2139     * instructions.  We use a pair of FETCH_Bs instead.
2140     *
2141     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2142     */
2143    /* op vAA, vBB, vCC */
2144    FETCH_B(r2, 1, 0)                   @ r2<- BB
2145    mov     r9, rINST, lsr #8           @ r9<- AA
2146    FETCH_B(r3, 1, 1)                   @ r3<- CC
2147    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2148    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2149    cmp     r0, #0                      @ null array object?
2150    beq     common_errNullObject        @ yes, bail
2151    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2152    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2153    cmp     r1, r3                      @ compare unsigned index, length
2154    bcs     common_errArrayIndex        @ index >= length, bail
2155    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2156    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2157    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2158    SET_VREG(r2, r9)                    @ vAA<- r2
2159    GOTO_OPCODE(ip)                     @ jump to next instruction
2160
2161
2162/* ------------------------------ */
2163    .balign 64
2164.L_OP_AGET_SHORT: /* 0x4a */
2165/* File: armv5te/OP_AGET_SHORT.S */
2166/* File: armv5te/OP_AGET.S */
2167    /*
2168     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2169     *
2170     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2171     * instructions.  We use a pair of FETCH_Bs instead.
2172     *
2173     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2174     */
2175    /* op vAA, vBB, vCC */
2176    FETCH_B(r2, 1, 0)                   @ r2<- BB
2177    mov     r9, rINST, lsr #8           @ r9<- AA
2178    FETCH_B(r3, 1, 1)                   @ r3<- CC
2179    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2180    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2181    cmp     r0, #0                      @ null array object?
2182    beq     common_errNullObject        @ yes, bail
2183    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2184    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2185    cmp     r1, r3                      @ compare unsigned index, length
2186    bcs     common_errArrayIndex        @ index >= length, bail
2187    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2188    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2189    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2190    SET_VREG(r2, r9)                    @ vAA<- r2
2191    GOTO_OPCODE(ip)                     @ jump to next instruction
2192
2193
2194/* ------------------------------ */
2195    .balign 64
2196.L_OP_APUT: /* 0x4b */
2197/* File: armv5te/OP_APUT.S */
2198    /*
2199     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2200     *
2201     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2202     * instructions.  We use a pair of FETCH_Bs instead.
2203     *
2204     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2205     */
2206    /* op vAA, vBB, vCC */
2207    FETCH_B(r2, 1, 0)                   @ r2<- BB
2208    mov     r9, rINST, lsr #8           @ r9<- AA
2209    FETCH_B(r3, 1, 1)                   @ r3<- CC
2210    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2211    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2212    cmp     r0, #0                      @ null array object?
2213    beq     common_errNullObject        @ yes, bail
2214    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2215    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2216    cmp     r1, r3                      @ compare unsigned index, length
2217    bcs     common_errArrayIndex        @ index >= length, bail
2218    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2219    GET_VREG(r2, r9)                    @ r2<- vAA
2220    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2221    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2222    GOTO_OPCODE(ip)                     @ jump to next instruction
2223
2224/* ------------------------------ */
2225    .balign 64
2226.L_OP_APUT_WIDE: /* 0x4c */
2227/* File: armv5te/OP_APUT_WIDE.S */
2228    /*
2229     * Array put, 64 bits.  vBB[vCC] <- vAA.
2230     *
2231     * Arrays of long/double are 64-bit aligned, so it's okay to use STRD.
2232     */
2233    /* aput-wide vAA, vBB, vCC */
2234    FETCH(r0, 1)                        @ r0<- CCBB
2235    mov     r9, rINST, lsr #8           @ r9<- AA
2236    and     r2, r0, #255                @ r2<- BB
2237    mov     r3, r0, lsr #8              @ r3<- CC
2238    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2239    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2240    cmp     r0, #0                      @ null array object?
2241    beq     common_errNullObject        @ yes, bail
2242    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2243    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2244    cmp     r1, r3                      @ compare unsigned index, length
2245    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2246    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2247    b       common_errArrayIndex        @ index >= length, bail
2248    @ May want to swap the order of these two branches depending on how the
2249    @ branch prediction (if any) handles conditional forward branches vs.
2250    @ unconditional forward branches.
2251
2252/* ------------------------------ */
2253    .balign 64
2254.L_OP_APUT_OBJECT: /* 0x4d */
2255/* File: armv5te/OP_APUT_OBJECT.S */
2256    /*
2257     * Store an object into an array.  vBB[vCC] <- vAA.
2258     *
2259     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2260     * instructions.  We use a pair of FETCH_Bs instead.
2261     */
2262    /* op vAA, vBB, vCC */
2263    FETCH(r0, 1)                        @ r0<- CCBB
2264    mov     r9, rINST, lsr #8           @ r9<- AA
2265    and     r2, r0, #255                @ r2<- BB
2266    mov     r3, r0, lsr #8              @ r3<- CC
2267    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2268    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2269    cmp     rINST, #0                   @ null array object?
2270    GET_VREG(r9, r9)                    @ r9<- vAA
2271    beq     common_errNullObject        @ yes, bail
2272    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2273    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
2274    cmp     r0, r3                      @ compare unsigned index, length
2275    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2276    b       common_errArrayIndex        @ index >= length, bail
2277
2278
2279/* ------------------------------ */
2280    .balign 64
2281.L_OP_APUT_BOOLEAN: /* 0x4e */
2282/* File: armv5te/OP_APUT_BOOLEAN.S */
2283/* File: armv5te/OP_APUT.S */
2284    /*
2285     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2286     *
2287     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2288     * instructions.  We use a pair of FETCH_Bs instead.
2289     *
2290     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2291     */
2292    /* op vAA, vBB, vCC */
2293    FETCH_B(r2, 1, 0)                   @ r2<- BB
2294    mov     r9, rINST, lsr #8           @ r9<- AA
2295    FETCH_B(r3, 1, 1)                   @ r3<- CC
2296    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2297    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2298    cmp     r0, #0                      @ null array object?
2299    beq     common_errNullObject        @ yes, bail
2300    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2301    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2302    cmp     r1, r3                      @ compare unsigned index, length
2303    bcs     common_errArrayIndex        @ index >= length, bail
2304    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2305    GET_VREG(r2, r9)                    @ r2<- vAA
2306    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2307    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2308    GOTO_OPCODE(ip)                     @ jump to next instruction
2309
2310
2311/* ------------------------------ */
2312    .balign 64
2313.L_OP_APUT_BYTE: /* 0x4f */
2314/* File: armv5te/OP_APUT_BYTE.S */
2315/* File: armv5te/OP_APUT.S */
2316    /*
2317     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2318     *
2319     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2320     * instructions.  We use a pair of FETCH_Bs instead.
2321     *
2322     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2323     */
2324    /* op vAA, vBB, vCC */
2325    FETCH_B(r2, 1, 0)                   @ r2<- BB
2326    mov     r9, rINST, lsr #8           @ r9<- AA
2327    FETCH_B(r3, 1, 1)                   @ r3<- CC
2328    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2329    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2330    cmp     r0, #0                      @ null array object?
2331    beq     common_errNullObject        @ yes, bail
2332    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2333    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2334    cmp     r1, r3                      @ compare unsigned index, length
2335    bcs     common_errArrayIndex        @ index >= length, bail
2336    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2337    GET_VREG(r2, r9)                    @ r2<- vAA
2338    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2339    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2340    GOTO_OPCODE(ip)                     @ jump to next instruction
2341
2342
2343/* ------------------------------ */
2344    .balign 64
2345.L_OP_APUT_CHAR: /* 0x50 */
2346/* File: armv5te/OP_APUT_CHAR.S */
2347/* File: armv5te/OP_APUT.S */
2348    /*
2349     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2350     *
2351     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2352     * instructions.  We use a pair of FETCH_Bs instead.
2353     *
2354     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2355     */
2356    /* op vAA, vBB, vCC */
2357    FETCH_B(r2, 1, 0)                   @ r2<- BB
2358    mov     r9, rINST, lsr #8           @ r9<- AA
2359    FETCH_B(r3, 1, 1)                   @ r3<- CC
2360    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2361    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2362    cmp     r0, #0                      @ null array object?
2363    beq     common_errNullObject        @ yes, bail
2364    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2365    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2366    cmp     r1, r3                      @ compare unsigned index, length
2367    bcs     common_errArrayIndex        @ index >= length, bail
2368    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2369    GET_VREG(r2, r9)                    @ r2<- vAA
2370    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2371    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2372    GOTO_OPCODE(ip)                     @ jump to next instruction
2373
2374
2375/* ------------------------------ */
2376    .balign 64
2377.L_OP_APUT_SHORT: /* 0x51 */
2378/* File: armv5te/OP_APUT_SHORT.S */
2379/* File: armv5te/OP_APUT.S */
2380    /*
2381     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2382     *
2383     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2384     * instructions.  We use a pair of FETCH_Bs instead.
2385     *
2386     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2387     */
2388    /* op vAA, vBB, vCC */
2389    FETCH_B(r2, 1, 0)                   @ r2<- BB
2390    mov     r9, rINST, lsr #8           @ r9<- AA
2391    FETCH_B(r3, 1, 1)                   @ r3<- CC
2392    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2393    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2394    cmp     r0, #0                      @ null array object?
2395    beq     common_errNullObject        @ yes, bail
2396    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2397    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2398    cmp     r1, r3                      @ compare unsigned index, length
2399    bcs     common_errArrayIndex        @ index >= length, bail
2400    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2401    GET_VREG(r2, r9)                    @ r2<- vAA
2402    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2403    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2404    GOTO_OPCODE(ip)                     @ jump to next instruction
2405
2406
2407/* ------------------------------ */
2408    .balign 64
2409.L_OP_IGET: /* 0x52 */
2410/* File: armv5te/OP_IGET.S */
2411    /*
2412     * General 32-bit instance field get.
2413     *
2414     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2415     */
2416    /* op vA, vB, field@CCCC */
2417    mov     r0, rINST, lsr #12          @ r0<- B
2418    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2419    FETCH(r1, 1)                        @ r1<- field ref CCCC
2420    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2421    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2422    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2423    cmp     r0, #0                      @ is resolved entry null?
2424    bne     .LOP_IGET_finish          @ no, already resolved
24258:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2426    EXPORT_PC()                         @ resolve() could throw
2427    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2428    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2429    cmp     r0, #0
2430    bne     .LOP_IGET_finish
2431    b       common_exceptionThrown
2432
2433/* ------------------------------ */
2434    .balign 64
2435.L_OP_IGET_WIDE: /* 0x53 */
2436/* File: armv5te/OP_IGET_WIDE.S */
2437    /*
2438     * Wide 32-bit instance field get.
2439     */
2440    /* iget-wide vA, vB, field@CCCC */
2441    mov     r0, rINST, lsr #12          @ r0<- B
2442    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2443    FETCH(r1, 1)                        @ r1<- field ref CCCC
2444    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2445    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2446    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2447    cmp     r0, #0                      @ is resolved entry null?
2448    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24498:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2450    EXPORT_PC()                         @ resolve() could throw
2451    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2452    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2453    cmp     r0, #0
2454    bne     .LOP_IGET_WIDE_finish
2455    b       common_exceptionThrown
2456
2457/* ------------------------------ */
2458    .balign 64
2459.L_OP_IGET_OBJECT: /* 0x54 */
2460/* File: armv5te/OP_IGET_OBJECT.S */
2461/* File: armv5te/OP_IGET.S */
2462    /*
2463     * General 32-bit instance field get.
2464     *
2465     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2466     */
2467    /* op vA, vB, field@CCCC */
2468    mov     r0, rINST, lsr #12          @ r0<- B
2469    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2470    FETCH(r1, 1)                        @ r1<- field ref CCCC
2471    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2472    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2473    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2474    cmp     r0, #0                      @ is resolved entry null?
2475    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24768:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2477    EXPORT_PC()                         @ resolve() could throw
2478    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2479    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2480    cmp     r0, #0
2481    bne     .LOP_IGET_OBJECT_finish
2482    b       common_exceptionThrown
2483
2484
2485/* ------------------------------ */
2486    .balign 64
2487.L_OP_IGET_BOOLEAN: /* 0x55 */
2488/* File: armv5te/OP_IGET_BOOLEAN.S */
2489@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2490/* File: armv5te/OP_IGET.S */
2491    /*
2492     * General 32-bit instance field get.
2493     *
2494     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2495     */
2496    /* op vA, vB, field@CCCC */
2497    mov     r0, rINST, lsr #12          @ r0<- B
2498    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2499    FETCH(r1, 1)                        @ r1<- field ref CCCC
2500    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2501    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2502    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2503    cmp     r0, #0                      @ is resolved entry null?
2504    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25058:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2506    EXPORT_PC()                         @ resolve() could throw
2507    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2508    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2509    cmp     r0, #0
2510    bne     .LOP_IGET_BOOLEAN_finish
2511    b       common_exceptionThrown
2512
2513
2514/* ------------------------------ */
2515    .balign 64
2516.L_OP_IGET_BYTE: /* 0x56 */
2517/* File: armv5te/OP_IGET_BYTE.S */
2518@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2519/* File: armv5te/OP_IGET.S */
2520    /*
2521     * General 32-bit instance field get.
2522     *
2523     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2524     */
2525    /* op vA, vB, field@CCCC */
2526    mov     r0, rINST, lsr #12          @ r0<- B
2527    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2528    FETCH(r1, 1)                        @ r1<- field ref CCCC
2529    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2530    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2531    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2532    cmp     r0, #0                      @ is resolved entry null?
2533    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25348:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2535    EXPORT_PC()                         @ resolve() could throw
2536    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2537    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2538    cmp     r0, #0
2539    bne     .LOP_IGET_BYTE_finish
2540    b       common_exceptionThrown
2541
2542
2543/* ------------------------------ */
2544    .balign 64
2545.L_OP_IGET_CHAR: /* 0x57 */
2546/* File: armv5te/OP_IGET_CHAR.S */
2547@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2548/* File: armv5te/OP_IGET.S */
2549    /*
2550     * General 32-bit instance field get.
2551     *
2552     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2553     */
2554    /* op vA, vB, field@CCCC */
2555    mov     r0, rINST, lsr #12          @ r0<- B
2556    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2557    FETCH(r1, 1)                        @ r1<- field ref CCCC
2558    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2559    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2560    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2561    cmp     r0, #0                      @ is resolved entry null?
2562    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25638:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2564    EXPORT_PC()                         @ resolve() could throw
2565    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2566    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2567    cmp     r0, #0
2568    bne     .LOP_IGET_CHAR_finish
2569    b       common_exceptionThrown
2570
2571
2572/* ------------------------------ */
2573    .balign 64
2574.L_OP_IGET_SHORT: /* 0x58 */
2575/* File: armv5te/OP_IGET_SHORT.S */
2576@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2577/* File: armv5te/OP_IGET.S */
2578    /*
2579     * General 32-bit instance field get.
2580     *
2581     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2582     */
2583    /* op vA, vB, field@CCCC */
2584    mov     r0, rINST, lsr #12          @ r0<- B
2585    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2586    FETCH(r1, 1)                        @ r1<- field ref CCCC
2587    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2588    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2589    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2590    cmp     r0, #0                      @ is resolved entry null?
2591    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
25928:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2593    EXPORT_PC()                         @ resolve() could throw
2594    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2595    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2596    cmp     r0, #0
2597    bne     .LOP_IGET_SHORT_finish
2598    b       common_exceptionThrown
2599
2600
2601/* ------------------------------ */
2602    .balign 64
2603.L_OP_IPUT: /* 0x59 */
2604/* File: armv5te/OP_IPUT.S */
2605    /*
2606     * General 32-bit instance field put.
2607     *
2608     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2609     */
2610    /* op vA, vB, field@CCCC */
2611    mov     r0, rINST, lsr #12          @ r0<- B
2612    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2613    FETCH(r1, 1)                        @ r1<- field ref CCCC
2614    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2615    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2616    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2617    cmp     r0, #0                      @ is resolved entry null?
2618    bne     .LOP_IPUT_finish          @ no, already resolved
26198:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2620    EXPORT_PC()                         @ resolve() could throw
2621    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2622    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2623    cmp     r0, #0                      @ success?
2624    bne     .LOP_IPUT_finish          @ yes, finish up
2625    b       common_exceptionThrown
2626
2627/* ------------------------------ */
2628    .balign 64
2629.L_OP_IPUT_WIDE: /* 0x5a */
2630/* File: armv5te/OP_IPUT_WIDE.S */
2631    /* iput-wide vA, vB, field@CCCC */
2632    mov     r0, rINST, lsr #12          @ r0<- B
2633    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2634    FETCH(r1, 1)                        @ r1<- field ref CCCC
2635    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2636    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2637    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2638    cmp     r0, #0                      @ is resolved entry null?
2639    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26408:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2641    EXPORT_PC()                         @ resolve() could throw
2642    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2643    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2644    cmp     r0, #0                      @ success?
2645    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2646    b       common_exceptionThrown
2647
2648/* ------------------------------ */
2649    .balign 64
2650.L_OP_IPUT_OBJECT: /* 0x5b */
2651/* File: armv5te/OP_IPUT_OBJECT.S */
2652    /*
2653     * 32-bit instance field put.
2654     *
2655     * for: iput-object, iput-object-volatile
2656     */
2657    /* op vA, vB, field@CCCC */
2658    mov     r0, rINST, lsr #12          @ r0<- B
2659    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2660    FETCH(r1, 1)                        @ r1<- field ref CCCC
2661    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2662    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2663    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2664    cmp     r0, #0                      @ is resolved entry null?
2665    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26668:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2667    EXPORT_PC()                         @ resolve() could throw
2668    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2669    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2670    cmp     r0, #0                      @ success?
2671    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2672    b       common_exceptionThrown
2673
2674/* ------------------------------ */
2675    .balign 64
2676.L_OP_IPUT_BOOLEAN: /* 0x5c */
2677/* File: armv5te/OP_IPUT_BOOLEAN.S */
2678@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2679/* File: armv5te/OP_IPUT.S */
2680    /*
2681     * General 32-bit instance field put.
2682     *
2683     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2684     */
2685    /* op vA, vB, field@CCCC */
2686    mov     r0, rINST, lsr #12          @ r0<- B
2687    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2688    FETCH(r1, 1)                        @ r1<- field ref CCCC
2689    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2690    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2691    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2692    cmp     r0, #0                      @ is resolved entry null?
2693    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
26948:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2695    EXPORT_PC()                         @ resolve() could throw
2696    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2697    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2698    cmp     r0, #0                      @ success?
2699    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2700    b       common_exceptionThrown
2701
2702
2703/* ------------------------------ */
2704    .balign 64
2705.L_OP_IPUT_BYTE: /* 0x5d */
2706/* File: armv5te/OP_IPUT_BYTE.S */
2707@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2708/* File: armv5te/OP_IPUT.S */
2709    /*
2710     * General 32-bit instance field put.
2711     *
2712     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2713     */
2714    /* op vA, vB, field@CCCC */
2715    mov     r0, rINST, lsr #12          @ r0<- B
2716    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2717    FETCH(r1, 1)                        @ r1<- field ref CCCC
2718    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2719    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2720    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2721    cmp     r0, #0                      @ is resolved entry null?
2722    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27238:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2724    EXPORT_PC()                         @ resolve() could throw
2725    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2726    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2727    cmp     r0, #0                      @ success?
2728    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2729    b       common_exceptionThrown
2730
2731
2732/* ------------------------------ */
2733    .balign 64
2734.L_OP_IPUT_CHAR: /* 0x5e */
2735/* File: armv5te/OP_IPUT_CHAR.S */
2736@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2737/* File: armv5te/OP_IPUT.S */
2738    /*
2739     * General 32-bit instance field put.
2740     *
2741     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2742     */
2743    /* op vA, vB, field@CCCC */
2744    mov     r0, rINST, lsr #12          @ r0<- B
2745    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2746    FETCH(r1, 1)                        @ r1<- field ref CCCC
2747    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2748    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2749    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2750    cmp     r0, #0                      @ is resolved entry null?
2751    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27528:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2753    EXPORT_PC()                         @ resolve() could throw
2754    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2755    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2756    cmp     r0, #0                      @ success?
2757    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2758    b       common_exceptionThrown
2759
2760
2761/* ------------------------------ */
2762    .balign 64
2763.L_OP_IPUT_SHORT: /* 0x5f */
2764/* File: armv5te/OP_IPUT_SHORT.S */
2765@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2766/* File: armv5te/OP_IPUT.S */
2767    /*
2768     * General 32-bit instance field put.
2769     *
2770     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2771     */
2772    /* op vA, vB, field@CCCC */
2773    mov     r0, rINST, lsr #12          @ r0<- B
2774    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2775    FETCH(r1, 1)                        @ r1<- field ref CCCC
2776    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2777    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2778    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2779    cmp     r0, #0                      @ is resolved entry null?
2780    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
27818:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2782    EXPORT_PC()                         @ resolve() could throw
2783    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2784    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2785    cmp     r0, #0                      @ success?
2786    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2787    b       common_exceptionThrown
2788
2789
2790/* ------------------------------ */
2791    .balign 64
2792.L_OP_SGET: /* 0x60 */
2793/* File: armv5te/OP_SGET.S */
2794    /*
2795     * General 32-bit SGET handler.
2796     *
2797     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2798     */
2799    /* op vAA, field@BBBB */
2800    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2801    FETCH(r1, 1)                        @ r1<- field ref BBBB
2802    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2803    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2804    cmp     r0, #0                      @ is resolved entry null?
2805    beq     .LOP_SGET_resolve         @ yes, do resolve
2806.LOP_SGET_finish: @ field ptr in r0
2807    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2808    @ no-op                             @ acquiring load
2809    mov     r2, rINST, lsr #8           @ r2<- AA
2810    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2811    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2812    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2813    GOTO_OPCODE(ip)                     @ jump to next instruction
2814
2815/* ------------------------------ */
2816    .balign 64
2817.L_OP_SGET_WIDE: /* 0x61 */
2818/* File: armv5te/OP_SGET_WIDE.S */
2819    /*
2820     * 64-bit SGET handler.
2821     */
2822    /* sget-wide vAA, field@BBBB */
2823    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2824    FETCH(r1, 1)                        @ r1<- field ref BBBB
2825    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2826    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2827    cmp     r0, #0                      @ is resolved entry null?
2828    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2829.LOP_SGET_WIDE_finish:
2830    mov     r9, rINST, lsr #8           @ r9<- AA
2831    .if 0
2832    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2833    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2834    .else
2835    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
2836    .endif
2837    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2838    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2839    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2840    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2841    GOTO_OPCODE(ip)                     @ jump to next instruction
2842
2843/* ------------------------------ */
2844    .balign 64
2845.L_OP_SGET_OBJECT: /* 0x62 */
2846/* File: armv5te/OP_SGET_OBJECT.S */
2847/* File: armv5te/OP_SGET.S */
2848    /*
2849     * General 32-bit SGET handler.
2850     *
2851     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2852     */
2853    /* op vAA, field@BBBB */
2854    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2855    FETCH(r1, 1)                        @ r1<- field ref BBBB
2856    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2857    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2858    cmp     r0, #0                      @ is resolved entry null?
2859    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2860.LOP_SGET_OBJECT_finish: @ field ptr in r0
2861    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2862    @ no-op                             @ acquiring load
2863    mov     r2, rINST, lsr #8           @ r2<- AA
2864    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2865    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2866    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2867    GOTO_OPCODE(ip)                     @ jump to next instruction
2868
2869
2870/* ------------------------------ */
2871    .balign 64
2872.L_OP_SGET_BOOLEAN: /* 0x63 */
2873/* File: armv5te/OP_SGET_BOOLEAN.S */
2874/* File: armv5te/OP_SGET.S */
2875    /*
2876     * General 32-bit SGET handler.
2877     *
2878     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2879     */
2880    /* op vAA, field@BBBB */
2881    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2882    FETCH(r1, 1)                        @ r1<- field ref BBBB
2883    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2884    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2885    cmp     r0, #0                      @ is resolved entry null?
2886    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2887.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2888    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2889    @ no-op                             @ acquiring load
2890    mov     r2, rINST, lsr #8           @ r2<- AA
2891    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2892    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2893    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2894    GOTO_OPCODE(ip)                     @ jump to next instruction
2895
2896
2897/* ------------------------------ */
2898    .balign 64
2899.L_OP_SGET_BYTE: /* 0x64 */
2900/* File: armv5te/OP_SGET_BYTE.S */
2901/* File: armv5te/OP_SGET.S */
2902    /*
2903     * General 32-bit SGET handler.
2904     *
2905     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2906     */
2907    /* op vAA, field@BBBB */
2908    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2909    FETCH(r1, 1)                        @ r1<- field ref BBBB
2910    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2911    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2912    cmp     r0, #0                      @ is resolved entry null?
2913    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2914.LOP_SGET_BYTE_finish: @ field ptr in r0
2915    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2916    @ no-op                             @ acquiring load
2917    mov     r2, rINST, lsr #8           @ r2<- AA
2918    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2919    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2920    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2921    GOTO_OPCODE(ip)                     @ jump to next instruction
2922
2923
2924/* ------------------------------ */
2925    .balign 64
2926.L_OP_SGET_CHAR: /* 0x65 */
2927/* File: armv5te/OP_SGET_CHAR.S */
2928/* File: armv5te/OP_SGET.S */
2929    /*
2930     * General 32-bit SGET handler.
2931     *
2932     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2933     */
2934    /* op vAA, field@BBBB */
2935    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2936    FETCH(r1, 1)                        @ r1<- field ref BBBB
2937    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2938    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2939    cmp     r0, #0                      @ is resolved entry null?
2940    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2941.LOP_SGET_CHAR_finish: @ field ptr in r0
2942    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2943    @ no-op                             @ acquiring load
2944    mov     r2, rINST, lsr #8           @ r2<- AA
2945    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2946    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2948    GOTO_OPCODE(ip)                     @ jump to next instruction
2949
2950
2951/* ------------------------------ */
2952    .balign 64
2953.L_OP_SGET_SHORT: /* 0x66 */
2954/* File: armv5te/OP_SGET_SHORT.S */
2955/* File: armv5te/OP_SGET.S */
2956    /*
2957     * General 32-bit SGET handler.
2958     *
2959     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2960     */
2961    /* op vAA, field@BBBB */
2962    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2963    FETCH(r1, 1)                        @ r1<- field ref BBBB
2964    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2965    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2966    cmp     r0, #0                      @ is resolved entry null?
2967    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2968.LOP_SGET_SHORT_finish: @ field ptr in r0
2969    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2970    @ no-op                             @ acquiring load
2971    mov     r2, rINST, lsr #8           @ r2<- AA
2972    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2973    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2974    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2975    GOTO_OPCODE(ip)                     @ jump to next instruction
2976
2977
2978/* ------------------------------ */
2979    .balign 64
2980.L_OP_SPUT: /* 0x67 */
2981/* File: armv5te/OP_SPUT.S */
2982    /*
2983     * General 32-bit SPUT handler.
2984     *
2985     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
2986     */
2987    /* op vAA, field@BBBB */
2988    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2989    FETCH(r1, 1)                        @ r1<- field ref BBBB
2990    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2991    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2992    cmp     r0, #0                      @ is resolved entry null?
2993    beq     .LOP_SPUT_resolve         @ yes, do resolve
2994.LOP_SPUT_finish:   @ field ptr in r0
2995    mov     r2, rINST, lsr #8           @ r2<- AA
2996    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2997    GET_VREG(r1, r2)                    @ r1<- fp[AA]
2998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2999    @ no-op                             @ releasing store
3000    str     r1, [r0, #offStaticField_value] @ field<- vAA
3001    GOTO_OPCODE(ip)                     @ jump to next instruction
3002
3003/* ------------------------------ */
3004    .balign 64
3005.L_OP_SPUT_WIDE: /* 0x68 */
3006/* File: armv5te/OP_SPUT_WIDE.S */
3007    /*
3008     * 64-bit SPUT handler.
3009     */
3010    /* sput-wide vAA, field@BBBB */
3011    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
3012    FETCH(r1, 1)                        @ r1<- field ref BBBB
3013    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3014    mov     r9, rINST, lsr #8           @ r9<- AA
3015    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3016    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3017    cmp     r2, #0                      @ is resolved entry null?
3018    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3019.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3020    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3021    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3022    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3023    .if 0
3024    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3025    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3026    .else
3027    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
3028    .endif
3029    GOTO_OPCODE(r10)                    @ jump to next instruction
3030
3031/* ------------------------------ */
3032    .balign 64
3033.L_OP_SPUT_OBJECT: /* 0x69 */
3034/* File: armv5te/OP_SPUT_OBJECT.S */
3035    /*
3036     * 32-bit SPUT handler for objects
3037     *
3038     * for: sput-object, sput-object-volatile
3039     */
3040    /* op vAA, field@BBBB */
3041    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3042    FETCH(r1, 1)                        @ r1<- field ref BBBB
3043    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3044    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3045    cmp     r0, #0                      @ is resolved entry null?
3046    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3047    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3048    EXPORT_PC()                         @ resolve() could throw, so export now
3049    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3050    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3051    cmp     r0, #0                      @ success?
3052    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3053    b       common_exceptionThrown      @ no, handle exception
3054
3055
3056/* ------------------------------ */
3057    .balign 64
3058.L_OP_SPUT_BOOLEAN: /* 0x6a */
3059/* File: armv5te/OP_SPUT_BOOLEAN.S */
3060/* File: armv5te/OP_SPUT.S */
3061    /*
3062     * General 32-bit SPUT handler.
3063     *
3064     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3065     */
3066    /* op vAA, field@BBBB */
3067    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3068    FETCH(r1, 1)                        @ r1<- field ref BBBB
3069    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3070    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3071    cmp     r0, #0                      @ is resolved entry null?
3072    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3073.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3074    mov     r2, rINST, lsr #8           @ r2<- AA
3075    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3076    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3077    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3078    @ no-op                             @ releasing store
3079    str     r1, [r0, #offStaticField_value] @ field<- vAA
3080    GOTO_OPCODE(ip)                     @ jump to next instruction
3081
3082
3083/* ------------------------------ */
3084    .balign 64
3085.L_OP_SPUT_BYTE: /* 0x6b */
3086/* File: armv5te/OP_SPUT_BYTE.S */
3087/* File: armv5te/OP_SPUT.S */
3088    /*
3089     * General 32-bit SPUT handler.
3090     *
3091     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3092     */
3093    /* op vAA, field@BBBB */
3094    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3095    FETCH(r1, 1)                        @ r1<- field ref BBBB
3096    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3097    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3098    cmp     r0, #0                      @ is resolved entry null?
3099    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3100.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3101    mov     r2, rINST, lsr #8           @ r2<- AA
3102    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3103    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3104    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3105    @ no-op                             @ releasing store
3106    str     r1, [r0, #offStaticField_value] @ field<- vAA
3107    GOTO_OPCODE(ip)                     @ jump to next instruction
3108
3109
3110/* ------------------------------ */
3111    .balign 64
3112.L_OP_SPUT_CHAR: /* 0x6c */
3113/* File: armv5te/OP_SPUT_CHAR.S */
3114/* File: armv5te/OP_SPUT.S */
3115    /*
3116     * General 32-bit SPUT handler.
3117     *
3118     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3119     */
3120    /* op vAA, field@BBBB */
3121    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3122    FETCH(r1, 1)                        @ r1<- field ref BBBB
3123    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3124    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3125    cmp     r0, #0                      @ is resolved entry null?
3126    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3127.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3128    mov     r2, rINST, lsr #8           @ r2<- AA
3129    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3130    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3131    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3132    @ no-op                             @ releasing store
3133    str     r1, [r0, #offStaticField_value] @ field<- vAA
3134    GOTO_OPCODE(ip)                     @ jump to next instruction
3135
3136
3137/* ------------------------------ */
3138    .balign 64
3139.L_OP_SPUT_SHORT: /* 0x6d */
3140/* File: armv5te/OP_SPUT_SHORT.S */
3141/* File: armv5te/OP_SPUT.S */
3142    /*
3143     * General 32-bit SPUT handler.
3144     *
3145     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3146     */
3147    /* op vAA, field@BBBB */
3148    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3149    FETCH(r1, 1)                        @ r1<- field ref BBBB
3150    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3151    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3152    cmp     r0, #0                      @ is resolved entry null?
3153    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3154.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3155    mov     r2, rINST, lsr #8           @ r2<- AA
3156    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3157    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3159    @ no-op                             @ releasing store
3160    str     r1, [r0, #offStaticField_value] @ field<- vAA
3161    GOTO_OPCODE(ip)                     @ jump to next instruction
3162
3163
3164/* ------------------------------ */
3165    .balign 64
3166.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3167/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3168    /*
3169     * Handle a virtual method call.
3170     *
3171     * for: invoke-virtual, invoke-virtual/range
3172     */
3173    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3174    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3175    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3176    FETCH(r1, 1)                        @ r1<- BBBB
3177    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3178    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3179    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3180    .if     (!0)
3181    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3182    .endif
3183    cmp     r0, #0                      @ already resolved?
3184    EXPORT_PC()                         @ must export for invoke
3185    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3186    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3187    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3188    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3189    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3190    cmp     r0, #0                      @ got null?
3191    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3192    b       common_exceptionThrown      @ yes, handle exception
3193
3194/* ------------------------------ */
3195    .balign 64
3196.L_OP_INVOKE_SUPER: /* 0x6f */
3197/* File: armv5te/OP_INVOKE_SUPER.S */
3198    /*
3199     * Handle a "super" method call.
3200     *
3201     * for: invoke-super, invoke-super/range
3202     */
3203    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3204    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3205    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3206    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3207    .if     (!0)
3208    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3209    .endif
3210    FETCH(r1, 1)                        @ r1<- BBBB
3211    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3212    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3213    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3214    cmp     r2, #0                      @ null "this"?
3215    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3216    beq     common_errNullObject        @ null "this", throw exception
3217    cmp     r0, #0                      @ already resolved?
3218    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3219    EXPORT_PC()                         @ must export for invoke
3220    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3221    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3222
3223/* ------------------------------ */
3224    .balign 64
3225.L_OP_INVOKE_DIRECT: /* 0x70 */
3226/* File: armv5te/OP_INVOKE_DIRECT.S */
3227    /*
3228     * Handle a direct method call.
3229     *
3230     * (We could defer the "is 'this' pointer null" test to the common
3231     * method invocation code, and use a flag to indicate that static
3232     * calls don't count.  If we do this as part of copying the arguments
3233     * out we could avoiding loading the first arg twice.)
3234     *
3235     * for: invoke-direct, invoke-direct/range
3236     */
3237    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3238    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3239    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3240    FETCH(r1, 1)                        @ r1<- BBBB
3241    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3242    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3243    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3244    .if     (!0)
3245    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3246    .endif
3247    cmp     r0, #0                      @ already resolved?
3248    EXPORT_PC()                         @ must export for invoke
3249    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3250    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3251.LOP_INVOKE_DIRECT_finish:
3252    cmp     r2, #0                      @ null "this" ref?
3253    bne     common_invokeMethodNoRange   @ no, continue on
3254    b       common_errNullObject        @ yes, throw exception
3255
3256/* ------------------------------ */
3257    .balign 64
3258.L_OP_INVOKE_STATIC: /* 0x71 */
3259/* File: armv5te/OP_INVOKE_STATIC.S */
3260    /*
3261     * Handle a static method call.
3262     *
3263     * for: invoke-static, invoke-static/range
3264     */
3265    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3266    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3267    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3268    FETCH(r1, 1)                        @ r1<- BBBB
3269    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3270    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3271    cmp     r0, #0                      @ already resolved?
3272    EXPORT_PC()                         @ must export for invoke
3273    bne     common_invokeMethodNoRange @ yes, continue on
32740:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3275    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3276    mov     r2, #METHOD_STATIC          @ resolver method type
3277    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3278    cmp     r0, #0                      @ got null?
3279    bne     common_invokeMethodNoRange @ no, continue
3280    b       common_exceptionThrown      @ yes, handle exception
3281
3282/* ------------------------------ */
3283    .balign 64
3284.L_OP_INVOKE_INTERFACE: /* 0x72 */
3285/* File: armv5te/OP_INVOKE_INTERFACE.S */
3286    /*
3287     * Handle an interface method call.
3288     *
3289     * for: invoke-interface, invoke-interface/range
3290     */
3291    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3292    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3293    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3294    FETCH(r1, 1)                        @ r1<- BBBB
3295    .if     (!0)
3296    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3297    .endif
3298    EXPORT_PC()                         @ must export for invoke
3299    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3300    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3301    cmp     r0, #0                      @ null obj?
3302    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3303    beq     common_errNullObject        @ yes, fail
3304    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3305    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3306    cmp     r0, #0                      @ failed?
3307    beq     common_exceptionThrown      @ yes, handle exception
3308    b       common_invokeMethodNoRange @ jump to common handler
3309
3310/* ------------------------------ */
3311    .balign 64
3312.L_OP_UNUSED_73: /* 0x73 */
3313/* File: armv5te/OP_UNUSED_73.S */
3314/* File: armv5te/unused.S */
3315    bl      common_abort
3316
3317
3318/* ------------------------------ */
3319    .balign 64
3320.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3321/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3322/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3323    /*
3324     * Handle a virtual method call.
3325     *
3326     * for: invoke-virtual, invoke-virtual/range
3327     */
3328    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3329    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3330    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3331    FETCH(r1, 1)                        @ r1<- BBBB
3332    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3333    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3334    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3335    .if     (!1)
3336    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3337    .endif
3338    cmp     r0, #0                      @ already resolved?
3339    EXPORT_PC()                         @ must export for invoke
3340    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3341    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3342    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3343    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3344    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3345    cmp     r0, #0                      @ got null?
3346    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3347    b       common_exceptionThrown      @ yes, handle exception
3348
3349
3350/* ------------------------------ */
3351    .balign 64
3352.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3353/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3354/* File: armv5te/OP_INVOKE_SUPER.S */
3355    /*
3356     * Handle a "super" method call.
3357     *
3358     * for: invoke-super, invoke-super/range
3359     */
3360    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3361    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3362    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3363    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3364    .if     (!1)
3365    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3366    .endif
3367    FETCH(r1, 1)                        @ r1<- BBBB
3368    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3369    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3370    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3371    cmp     r2, #0                      @ null "this"?
3372    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3373    beq     common_errNullObject        @ null "this", throw exception
3374    cmp     r0, #0                      @ already resolved?
3375    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3376    EXPORT_PC()                         @ must export for invoke
3377    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3378    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3379
3380
3381/* ------------------------------ */
3382    .balign 64
3383.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3384/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3385/* File: armv5te/OP_INVOKE_DIRECT.S */
3386    /*
3387     * Handle a direct method call.
3388     *
3389     * (We could defer the "is 'this' pointer null" test to the common
3390     * method invocation code, and use a flag to indicate that static
3391     * calls don't count.  If we do this as part of copying the arguments
3392     * out we could avoiding loading the first arg twice.)
3393     *
3394     * for: invoke-direct, invoke-direct/range
3395     */
3396    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3397    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3398    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3399    FETCH(r1, 1)                        @ r1<- BBBB
3400    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3401    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3402    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3403    .if     (!1)
3404    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3405    .endif
3406    cmp     r0, #0                      @ already resolved?
3407    EXPORT_PC()                         @ must export for invoke
3408    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3409    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3410.LOP_INVOKE_DIRECT_RANGE_finish:
3411    cmp     r2, #0                      @ null "this" ref?
3412    bne     common_invokeMethodRange   @ no, continue on
3413    b       common_errNullObject        @ yes, throw exception
3414
3415
3416/* ------------------------------ */
3417    .balign 64
3418.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3419/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3420/* File: armv5te/OP_INVOKE_STATIC.S */
3421    /*
3422     * Handle a static method call.
3423     *
3424     * for: invoke-static, invoke-static/range
3425     */
3426    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3427    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3428    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3429    FETCH(r1, 1)                        @ r1<- BBBB
3430    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3431    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3432    cmp     r0, #0                      @ already resolved?
3433    EXPORT_PC()                         @ must export for invoke
3434    bne     common_invokeMethodRange @ yes, continue on
34350:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3436    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3437    mov     r2, #METHOD_STATIC          @ resolver method type
3438    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3439    cmp     r0, #0                      @ got null?
3440    bne     common_invokeMethodRange @ no, continue
3441    b       common_exceptionThrown      @ yes, handle exception
3442
3443
3444/* ------------------------------ */
3445    .balign 64
3446.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3447/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3448/* File: armv5te/OP_INVOKE_INTERFACE.S */
3449    /*
3450     * Handle an interface method call.
3451     *
3452     * for: invoke-interface, invoke-interface/range
3453     */
3454    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3455    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3456    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3457    FETCH(r1, 1)                        @ r1<- BBBB
3458    .if     (!1)
3459    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3460    .endif
3461    EXPORT_PC()                         @ must export for invoke
3462    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3463    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3464    cmp     r0, #0                      @ null obj?
3465    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3466    beq     common_errNullObject        @ yes, fail
3467    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3468    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3469    cmp     r0, #0                      @ failed?
3470    beq     common_exceptionThrown      @ yes, handle exception
3471    b       common_invokeMethodRange @ jump to common handler
3472
3473
3474/* ------------------------------ */
3475    .balign 64
3476.L_OP_UNUSED_79: /* 0x79 */
3477/* File: armv5te/OP_UNUSED_79.S */
3478/* File: armv5te/unused.S */
3479    bl      common_abort
3480
3481
3482/* ------------------------------ */
3483    .balign 64
3484.L_OP_UNUSED_7A: /* 0x7a */
3485/* File: armv5te/OP_UNUSED_7A.S */
3486/* File: armv5te/unused.S */
3487    bl      common_abort
3488
3489
3490/* ------------------------------ */
3491    .balign 64
3492.L_OP_NEG_INT: /* 0x7b */
3493/* File: armv5te/OP_NEG_INT.S */
3494/* File: armv5te/unop.S */
3495    /*
3496     * Generic 32-bit unary operation.  Provide an "instr" line that
3497     * specifies an instruction that performs "result = op r0".
3498     * This could be an ARM instruction or a function call.
3499     *
3500     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3501     *      int-to-byte, int-to-char, int-to-short
3502     */
3503    /* unop vA, vB */
3504    mov     r3, rINST, lsr #12          @ r3<- B
3505    mov     r9, rINST, lsr #8           @ r9<- A+
3506    GET_VREG(r0, r3)                    @ r0<- vB
3507    and     r9, r9, #15
3508                               @ optional op; may set condition codes
3509    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3510    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3511    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3512    SET_VREG(r0, r9)                    @ vAA<- r0
3513    GOTO_OPCODE(ip)                     @ jump to next instruction
3514    /* 9-10 instructions */
3515
3516
3517/* ------------------------------ */
3518    .balign 64
3519.L_OP_NOT_INT: /* 0x7c */
3520/* File: armv5te/OP_NOT_INT.S */
3521/* File: armv5te/unop.S */
3522    /*
3523     * Generic 32-bit unary operation.  Provide an "instr" line that
3524     * specifies an instruction that performs "result = op r0".
3525     * This could be an ARM instruction or a function call.
3526     *
3527     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3528     *      int-to-byte, int-to-char, int-to-short
3529     */
3530    /* unop vA, vB */
3531    mov     r3, rINST, lsr #12          @ r3<- B
3532    mov     r9, rINST, lsr #8           @ r9<- A+
3533    GET_VREG(r0, r3)                    @ r0<- vB
3534    and     r9, r9, #15
3535                               @ optional op; may set condition codes
3536    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3537    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3538    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3539    SET_VREG(r0, r9)                    @ vAA<- r0
3540    GOTO_OPCODE(ip)                     @ jump to next instruction
3541    /* 9-10 instructions */
3542
3543
3544/* ------------------------------ */
3545    .balign 64
3546.L_OP_NEG_LONG: /* 0x7d */
3547/* File: armv5te/OP_NEG_LONG.S */
3548/* File: armv5te/unopWide.S */
3549    /*
3550     * Generic 64-bit unary operation.  Provide an "instr" line that
3551     * specifies an instruction that performs "result = op r0/r1".
3552     * This could be an ARM instruction or a function call.
3553     *
3554     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3555     */
3556    /* unop vA, vB */
3557    mov     r9, rINST, lsr #8           @ r9<- A+
3558    mov     r3, rINST, lsr #12          @ r3<- B
3559    and     r9, r9, #15
3560    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3561    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3562    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3563    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3564    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3565    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3566    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3567    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3568    GOTO_OPCODE(ip)                     @ jump to next instruction
3569    /* 12-13 instructions */
3570
3571
3572/* ------------------------------ */
3573    .balign 64
3574.L_OP_NOT_LONG: /* 0x7e */
3575/* File: armv5te/OP_NOT_LONG.S */
3576/* File: armv5te/unopWide.S */
3577    /*
3578     * Generic 64-bit unary operation.  Provide an "instr" line that
3579     * specifies an instruction that performs "result = op r0/r1".
3580     * This could be an ARM instruction or a function call.
3581     *
3582     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3583     */
3584    /* unop vA, vB */
3585    mov     r9, rINST, lsr #8           @ r9<- A+
3586    mov     r3, rINST, lsr #12          @ r3<- B
3587    and     r9, r9, #15
3588    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3589    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3590    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3591    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3592    mvn     r0, r0                           @ optional op; may set condition codes
3593    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3594    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3595    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3596    GOTO_OPCODE(ip)                     @ jump to next instruction
3597    /* 12-13 instructions */
3598
3599
3600/* ------------------------------ */
3601    .balign 64
3602.L_OP_NEG_FLOAT: /* 0x7f */
3603/* File: armv5te/OP_NEG_FLOAT.S */
3604/* File: armv5te/unop.S */
3605    /*
3606     * Generic 32-bit unary operation.  Provide an "instr" line that
3607     * specifies an instruction that performs "result = op r0".
3608     * This could be an ARM instruction or a function call.
3609     *
3610     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3611     *      int-to-byte, int-to-char, int-to-short
3612     */
3613    /* unop vA, vB */
3614    mov     r3, rINST, lsr #12          @ r3<- B
3615    mov     r9, rINST, lsr #8           @ r9<- A+
3616    GET_VREG(r0, r3)                    @ r0<- vB
3617    and     r9, r9, #15
3618                               @ optional op; may set condition codes
3619    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3620    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3621    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3622    SET_VREG(r0, r9)                    @ vAA<- r0
3623    GOTO_OPCODE(ip)                     @ jump to next instruction
3624    /* 9-10 instructions */
3625
3626
3627/* ------------------------------ */
3628    .balign 64
3629.L_OP_NEG_DOUBLE: /* 0x80 */
3630/* File: armv5te/OP_NEG_DOUBLE.S */
3631/* File: armv5te/unopWide.S */
3632    /*
3633     * Generic 64-bit unary operation.  Provide an "instr" line that
3634     * specifies an instruction that performs "result = op r0/r1".
3635     * This could be an ARM instruction or a function call.
3636     *
3637     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3638     */
3639    /* unop vA, vB */
3640    mov     r9, rINST, lsr #8           @ r9<- A+
3641    mov     r3, rINST, lsr #12          @ r3<- B
3642    and     r9, r9, #15
3643    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3644    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3645    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3646    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3647                               @ optional op; may set condition codes
3648    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3650    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3651    GOTO_OPCODE(ip)                     @ jump to next instruction
3652    /* 12-13 instructions */
3653
3654
3655/* ------------------------------ */
3656    .balign 64
3657.L_OP_INT_TO_LONG: /* 0x81 */
3658/* File: armv5te/OP_INT_TO_LONG.S */
3659/* File: armv5te/unopWider.S */
3660    /*
3661     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3662     * that specifies an instruction that performs "result = op r0", where
3663     * "result" is a 64-bit quantity in r0/r1.
3664     *
3665     * For: int-to-long, int-to-double, float-to-long, float-to-double
3666     */
3667    /* unop vA, vB */
3668    mov     r9, rINST, lsr #8           @ r9<- A+
3669    mov     r3, rINST, lsr #12          @ r3<- B
3670    and     r9, r9, #15
3671    GET_VREG(r0, r3)                    @ r0<- vB
3672    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3673                               @ optional op; may set condition codes
3674    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3675    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3676    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3677    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3678    GOTO_OPCODE(ip)                     @ jump to next instruction
3679    /* 10-11 instructions */
3680
3681
3682/* ------------------------------ */
3683    .balign 64
3684.L_OP_INT_TO_FLOAT: /* 0x82 */
3685/* File: arm-vfp/OP_INT_TO_FLOAT.S */
3686/* File: arm-vfp/funop.S */
3687    /*
3688     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3689     * line that specifies an instruction that performs "s1 = op s0".
3690     *
3691     * for: int-to-float, float-to-int
3692     */
3693    /* unop vA, vB */
3694    mov     r3, rINST, lsr #12          @ r3<- B
3695    mov     r9, rINST, lsr #8           @ r9<- A+
3696    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3697    flds    s0, [r3]                    @ s0<- vB
3698    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3699    and     r9, r9, #15                 @ r9<- A
3700    fsitos  s1, s0                              @ s1<- op
3701    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3702    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3703    fsts    s1, [r9]                    @ vA<- s1
3704    GOTO_OPCODE(ip)                     @ jump to next instruction
3705
3706
3707/* ------------------------------ */
3708    .balign 64
3709.L_OP_INT_TO_DOUBLE: /* 0x83 */
3710/* File: arm-vfp/OP_INT_TO_DOUBLE.S */
3711/* File: arm-vfp/funopWider.S */
3712    /*
3713     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3714     * "instr" line that specifies an instruction that performs "d0 = op s0".
3715     *
3716     * For: int-to-double, float-to-double
3717     */
3718    /* unop vA, vB */
3719    mov     r3, rINST, lsr #12          @ r3<- B
3720    mov     r9, rINST, lsr #8           @ r9<- A+
3721    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3722    flds    s0, [r3]                    @ s0<- vB
3723    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3724    and     r9, r9, #15                 @ r9<- A
3725    fsitod  d0, s0                              @ d0<- op
3726    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3727    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3728    fstd    d0, [r9]                    @ vA<- d0
3729    GOTO_OPCODE(ip)                     @ jump to next instruction
3730
3731
3732/* ------------------------------ */
3733    .balign 64
3734.L_OP_LONG_TO_INT: /* 0x84 */
3735/* File: armv5te/OP_LONG_TO_INT.S */
3736/* we ignore the high word, making this equivalent to a 32-bit reg move */
3737/* File: armv5te/OP_MOVE.S */
3738    /* for move, move-object, long-to-int */
3739    /* op vA, vB */
3740    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3741    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3742    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3743    GET_VREG(r2, r1)                    @ r2<- fp[B]
3744    and     r0, r0, #15
3745    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3746    SET_VREG(r2, r0)                    @ fp[A]<- r2
3747    GOTO_OPCODE(ip)                     @ execute next instruction
3748
3749
3750/* ------------------------------ */
3751    .balign 64
3752.L_OP_LONG_TO_FLOAT: /* 0x85 */
3753/* File: armv5te/OP_LONG_TO_FLOAT.S */
3754/* File: armv5te/unopNarrower.S */
3755    /*
3756     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3757     * that specifies an instruction that performs "result = op r0/r1", where
3758     * "result" is a 32-bit quantity in r0.
3759     *
3760     * For: long-to-float, double-to-int, double-to-float
3761     *
3762     * (This would work for long-to-int, but that instruction is actually
3763     * an exact match for OP_MOVE.)
3764     */
3765    /* unop vA, vB */
3766    mov     r3, rINST, lsr #12          @ r3<- B
3767    mov     r9, rINST, lsr #8           @ r9<- A+
3768    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3769    and     r9, r9, #15
3770    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3771    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3772                               @ optional op; may set condition codes
3773    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3774    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3775    SET_VREG(r0, r9)                    @ vA<- r0
3776    GOTO_OPCODE(ip)                     @ jump to next instruction
3777    /* 10-11 instructions */
3778
3779
3780/* ------------------------------ */
3781    .balign 64
3782.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3783/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3784/* File: armv5te/unopWide.S */
3785    /*
3786     * Generic 64-bit unary operation.  Provide an "instr" line that
3787     * specifies an instruction that performs "result = op r0/r1".
3788     * This could be an ARM instruction or a function call.
3789     *
3790     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3791     */
3792    /* unop vA, vB */
3793    mov     r9, rINST, lsr #8           @ r9<- A+
3794    mov     r3, rINST, lsr #12          @ r3<- B
3795    and     r9, r9, #15
3796    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3797    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3798    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3799    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3800                               @ optional op; may set condition codes
3801    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3803    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3804    GOTO_OPCODE(ip)                     @ jump to next instruction
3805    /* 12-13 instructions */
3806
3807
3808/* ------------------------------ */
3809    .balign 64
3810.L_OP_FLOAT_TO_INT: /* 0x87 */
3811/* File: arm-vfp/OP_FLOAT_TO_INT.S */
3812/* File: arm-vfp/funop.S */
3813    /*
3814     * Generic 32-bit unary floating-point operation.  Provide an "instr"
3815     * line that specifies an instruction that performs "s1 = op s0".
3816     *
3817     * for: int-to-float, float-to-int
3818     */
3819    /* unop vA, vB */
3820    mov     r3, rINST, lsr #12          @ r3<- B
3821    mov     r9, rINST, lsr #8           @ r9<- A+
3822    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3823    flds    s0, [r3]                    @ s0<- vB
3824    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3825    and     r9, r9, #15                 @ r9<- A
3826    ftosizs s1, s0                              @ s1<- op
3827    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3828    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3829    fsts    s1, [r9]                    @ vA<- s1
3830    GOTO_OPCODE(ip)                     @ jump to next instruction
3831
3832
3833/* ------------------------------ */
3834    .balign 64
3835.L_OP_FLOAT_TO_LONG: /* 0x88 */
3836/* File: armv5te/OP_FLOAT_TO_LONG.S */
3837@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3838/* File: armv5te/unopWider.S */
3839    /*
3840     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3841     * that specifies an instruction that performs "result = op r0", where
3842     * "result" is a 64-bit quantity in r0/r1.
3843     *
3844     * For: int-to-long, int-to-double, float-to-long, float-to-double
3845     */
3846    /* unop vA, vB */
3847    mov     r9, rINST, lsr #8           @ r9<- A+
3848    mov     r3, rINST, lsr #12          @ r3<- B
3849    and     r9, r9, #15
3850    GET_VREG(r0, r3)                    @ r0<- vB
3851    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3852                               @ optional op; may set condition codes
3853    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3854    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3855    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3856    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3857    GOTO_OPCODE(ip)                     @ jump to next instruction
3858    /* 10-11 instructions */
3859
3860
3861
3862/* ------------------------------ */
3863    .balign 64
3864.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3865/* File: arm-vfp/OP_FLOAT_TO_DOUBLE.S */
3866/* File: arm-vfp/funopWider.S */
3867    /*
3868     * Generic 32bit-to-64bit floating point unary operation.  Provide an
3869     * "instr" line that specifies an instruction that performs "d0 = op s0".
3870     *
3871     * For: int-to-double, float-to-double
3872     */
3873    /* unop vA, vB */
3874    mov     r3, rINST, lsr #12          @ r3<- B
3875    mov     r9, rINST, lsr #8           @ r9<- A+
3876    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3877    flds    s0, [r3]                    @ s0<- vB
3878    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3879    and     r9, r9, #15                 @ r9<- A
3880    fcvtds  d0, s0                              @ d0<- op
3881    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3882    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3883    fstd    d0, [r9]                    @ vA<- d0
3884    GOTO_OPCODE(ip)                     @ jump to next instruction
3885
3886
3887/* ------------------------------ */
3888    .balign 64
3889.L_OP_DOUBLE_TO_INT: /* 0x8a */
3890/* File: arm-vfp/OP_DOUBLE_TO_INT.S */
3891/* File: arm-vfp/funopNarrower.S */
3892    /*
3893     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3894     * "instr" line that specifies an instruction that performs "s0 = op d0".
3895     *
3896     * For: double-to-int, double-to-float
3897     */
3898    /* unop vA, vB */
3899    mov     r3, rINST, lsr #12          @ r3<- B
3900    mov     r9, rINST, lsr #8           @ r9<- A+
3901    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3902    fldd    d0, [r3]                    @ d0<- vB
3903    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3904    and     r9, r9, #15                 @ r9<- A
3905    ftosizd  s0, d0                              @ s0<- op
3906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3907    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3908    fsts    s0, [r9]                    @ vA<- s0
3909    GOTO_OPCODE(ip)                     @ jump to next instruction
3910
3911
3912/* ------------------------------ */
3913    .balign 64
3914.L_OP_DOUBLE_TO_LONG: /* 0x8b */
3915/* File: armv5te/OP_DOUBLE_TO_LONG.S */
3916@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
3917/* File: armv5te/unopWide.S */
3918    /*
3919     * Generic 64-bit unary operation.  Provide an "instr" line that
3920     * specifies an instruction that performs "result = op r0/r1".
3921     * This could be an ARM instruction or a function call.
3922     *
3923     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3924     */
3925    /* unop vA, vB */
3926    mov     r9, rINST, lsr #8           @ r9<- A+
3927    mov     r3, rINST, lsr #12          @ r3<- B
3928    and     r9, r9, #15
3929    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3930    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3931    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3932    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3933                               @ optional op; may set condition codes
3934    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
3935    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3936    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3937    GOTO_OPCODE(ip)                     @ jump to next instruction
3938    /* 12-13 instructions */
3939
3940
3941
3942/* ------------------------------ */
3943    .balign 64
3944.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
3945/* File: arm-vfp/OP_DOUBLE_TO_FLOAT.S */
3946/* File: arm-vfp/funopNarrower.S */
3947    /*
3948     * Generic 64bit-to-32bit unary floating point operation.  Provide an
3949     * "instr" line that specifies an instruction that performs "s0 = op d0".
3950     *
3951     * For: double-to-int, double-to-float
3952     */
3953    /* unop vA, vB */
3954    mov     r3, rINST, lsr #12          @ r3<- B
3955    mov     r9, rINST, lsr #8           @ r9<- A+
3956    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
3957    fldd    d0, [r3]                    @ d0<- vB
3958    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3959    and     r9, r9, #15                 @ r9<- A
3960    fcvtsd  s0, d0                              @ s0<- op
3961    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3962    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
3963    fsts    s0, [r9]                    @ vA<- s0
3964    GOTO_OPCODE(ip)                     @ jump to next instruction
3965
3966
3967/* ------------------------------ */
3968    .balign 64
3969.L_OP_INT_TO_BYTE: /* 0x8d */
3970/* File: armv5te/OP_INT_TO_BYTE.S */
3971/* File: armv5te/unop.S */
3972    /*
3973     * Generic 32-bit unary operation.  Provide an "instr" line that
3974     * specifies an instruction that performs "result = op r0".
3975     * This could be an ARM instruction or a function call.
3976     *
3977     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3978     *      int-to-byte, int-to-char, int-to-short
3979     */
3980    /* unop vA, vB */
3981    mov     r3, rINST, lsr #12          @ r3<- B
3982    mov     r9, rINST, lsr #8           @ r9<- A+
3983    GET_VREG(r0, r3)                    @ r0<- vB
3984    and     r9, r9, #15
3985    mov     r0, r0, asl #24                           @ optional op; may set condition codes
3986    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3987    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
3988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3989    SET_VREG(r0, r9)                    @ vAA<- r0
3990    GOTO_OPCODE(ip)                     @ jump to next instruction
3991    /* 9-10 instructions */
3992
3993
3994/* ------------------------------ */
3995    .balign 64
3996.L_OP_INT_TO_CHAR: /* 0x8e */
3997/* File: armv5te/OP_INT_TO_CHAR.S */
3998/* File: armv5te/unop.S */
3999    /*
4000     * Generic 32-bit unary operation.  Provide an "instr" line that
4001     * specifies an instruction that performs "result = op r0".
4002     * This could be an ARM instruction or a function call.
4003     *
4004     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4005     *      int-to-byte, int-to-char, int-to-short
4006     */
4007    /* unop vA, vB */
4008    mov     r3, rINST, lsr #12          @ r3<- B
4009    mov     r9, rINST, lsr #8           @ r9<- A+
4010    GET_VREG(r0, r3)                    @ r0<- vB
4011    and     r9, r9, #15
4012    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4013    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4014    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4015    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4016    SET_VREG(r0, r9)                    @ vAA<- r0
4017    GOTO_OPCODE(ip)                     @ jump to next instruction
4018    /* 9-10 instructions */
4019
4020
4021/* ------------------------------ */
4022    .balign 64
4023.L_OP_INT_TO_SHORT: /* 0x8f */
4024/* File: armv5te/OP_INT_TO_SHORT.S */
4025/* File: armv5te/unop.S */
4026    /*
4027     * Generic 32-bit unary operation.  Provide an "instr" line that
4028     * specifies an instruction that performs "result = op r0".
4029     * This could be an ARM instruction or a function call.
4030     *
4031     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4032     *      int-to-byte, int-to-char, int-to-short
4033     */
4034    /* unop vA, vB */
4035    mov     r3, rINST, lsr #12          @ r3<- B
4036    mov     r9, rINST, lsr #8           @ r9<- A+
4037    GET_VREG(r0, r3)                    @ r0<- vB
4038    and     r9, r9, #15
4039    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4040    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4041    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4042    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4043    SET_VREG(r0, r9)                    @ vAA<- r0
4044    GOTO_OPCODE(ip)                     @ jump to next instruction
4045    /* 9-10 instructions */
4046
4047
4048/* ------------------------------ */
4049    .balign 64
4050.L_OP_ADD_INT: /* 0x90 */
4051/* File: armv5te/OP_ADD_INT.S */
4052/* File: armv5te/binop.S */
4053    /*
4054     * Generic 32-bit binary operation.  Provide an "instr" line that
4055     * specifies an instruction that performs "result = r0 op r1".
4056     * This could be an ARM instruction or a function call.  (If the result
4057     * comes back in a register other than r0, you can override "result".)
4058     *
4059     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4060     * vCC (r1).  Useful for integer division and modulus.  Note that we
4061     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4062     * handles it correctly.
4063     *
4064     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4065     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4066     *      mul-float, div-float, rem-float
4067     */
4068    /* binop vAA, vBB, vCC */
4069    FETCH(r0, 1)                        @ r0<- CCBB
4070    mov     r9, rINST, lsr #8           @ r9<- AA
4071    mov     r3, r0, lsr #8              @ r3<- CC
4072    and     r2, r0, #255                @ r2<- BB
4073    GET_VREG(r1, r3)                    @ r1<- vCC
4074    GET_VREG(r0, r2)                    @ r0<- vBB
4075    .if 0
4076    cmp     r1, #0                      @ is second operand zero?
4077    beq     common_errDivideByZero
4078    .endif
4079
4080    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4081                               @ optional op; may set condition codes
4082    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4084    SET_VREG(r0, r9)               @ vAA<- r0
4085    GOTO_OPCODE(ip)                     @ jump to next instruction
4086    /* 11-14 instructions */
4087
4088
4089/* ------------------------------ */
4090    .balign 64
4091.L_OP_SUB_INT: /* 0x91 */
4092/* File: armv5te/OP_SUB_INT.S */
4093/* File: armv5te/binop.S */
4094    /*
4095     * Generic 32-bit binary operation.  Provide an "instr" line that
4096     * specifies an instruction that performs "result = r0 op r1".
4097     * This could be an ARM instruction or a function call.  (If the result
4098     * comes back in a register other than r0, you can override "result".)
4099     *
4100     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4101     * vCC (r1).  Useful for integer division and modulus.  Note that we
4102     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4103     * handles it correctly.
4104     *
4105     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4106     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4107     *      mul-float, div-float, rem-float
4108     */
4109    /* binop vAA, vBB, vCC */
4110    FETCH(r0, 1)                        @ r0<- CCBB
4111    mov     r9, rINST, lsr #8           @ r9<- AA
4112    mov     r3, r0, lsr #8              @ r3<- CC
4113    and     r2, r0, #255                @ r2<- BB
4114    GET_VREG(r1, r3)                    @ r1<- vCC
4115    GET_VREG(r0, r2)                    @ r0<- vBB
4116    .if 0
4117    cmp     r1, #0                      @ is second operand zero?
4118    beq     common_errDivideByZero
4119    .endif
4120
4121    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4122                               @ optional op; may set condition codes
4123    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4124    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4125    SET_VREG(r0, r9)               @ vAA<- r0
4126    GOTO_OPCODE(ip)                     @ jump to next instruction
4127    /* 11-14 instructions */
4128
4129
4130/* ------------------------------ */
4131    .balign 64
4132.L_OP_MUL_INT: /* 0x92 */
4133/* File: armv5te/OP_MUL_INT.S */
4134/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4135/* File: armv5te/binop.S */
4136    /*
4137     * Generic 32-bit binary operation.  Provide an "instr" line that
4138     * specifies an instruction that performs "result = r0 op r1".
4139     * This could be an ARM instruction or a function call.  (If the result
4140     * comes back in a register other than r0, you can override "result".)
4141     *
4142     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4143     * vCC (r1).  Useful for integer division and modulus.  Note that we
4144     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4145     * handles it correctly.
4146     *
4147     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4148     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4149     *      mul-float, div-float, rem-float
4150     */
4151    /* binop vAA, vBB, vCC */
4152    FETCH(r0, 1)                        @ r0<- CCBB
4153    mov     r9, rINST, lsr #8           @ r9<- AA
4154    mov     r3, r0, lsr #8              @ r3<- CC
4155    and     r2, r0, #255                @ r2<- BB
4156    GET_VREG(r1, r3)                    @ r1<- vCC
4157    GET_VREG(r0, r2)                    @ r0<- vBB
4158    .if 0
4159    cmp     r1, #0                      @ is second operand zero?
4160    beq     common_errDivideByZero
4161    .endif
4162
4163    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4164                               @ optional op; may set condition codes
4165    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4166    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4167    SET_VREG(r0, r9)               @ vAA<- r0
4168    GOTO_OPCODE(ip)                     @ jump to next instruction
4169    /* 11-14 instructions */
4170
4171
4172/* ------------------------------ */
4173    .balign 64
4174.L_OP_DIV_INT: /* 0x93 */
4175/* File: armv5te/OP_DIV_INT.S */
4176/* File: armv5te/binop.S */
4177    /*
4178     * Generic 32-bit binary operation.  Provide an "instr" line that
4179     * specifies an instruction that performs "result = r0 op r1".
4180     * This could be an ARM instruction or a function call.  (If the result
4181     * comes back in a register other than r0, you can override "result".)
4182     *
4183     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4184     * vCC (r1).  Useful for integer division and modulus.  Note that we
4185     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4186     * handles it correctly.
4187     *
4188     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4189     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4190     *      mul-float, div-float, rem-float
4191     */
4192    /* binop vAA, vBB, vCC */
4193    FETCH(r0, 1)                        @ r0<- CCBB
4194    mov     r9, rINST, lsr #8           @ r9<- AA
4195    mov     r3, r0, lsr #8              @ r3<- CC
4196    and     r2, r0, #255                @ r2<- BB
4197    GET_VREG(r1, r3)                    @ r1<- vCC
4198    GET_VREG(r0, r2)                    @ r0<- vBB
4199    .if 1
4200    cmp     r1, #0                      @ is second operand zero?
4201    beq     common_errDivideByZero
4202    .endif
4203
4204    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4205                               @ optional op; may set condition codes
4206    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4207    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4208    SET_VREG(r0, r9)               @ vAA<- r0
4209    GOTO_OPCODE(ip)                     @ jump to next instruction
4210    /* 11-14 instructions */
4211
4212
4213/* ------------------------------ */
4214    .balign 64
4215.L_OP_REM_INT: /* 0x94 */
4216/* File: armv5te/OP_REM_INT.S */
4217/* idivmod returns quotient in r0 and remainder in r1 */
4218/* File: armv5te/binop.S */
4219    /*
4220     * Generic 32-bit binary operation.  Provide an "instr" line that
4221     * specifies an instruction that performs "result = r0 op r1".
4222     * This could be an ARM instruction or a function call.  (If the result
4223     * comes back in a register other than r0, you can override "result".)
4224     *
4225     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4226     * vCC (r1).  Useful for integer division and modulus.  Note that we
4227     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4228     * handles it correctly.
4229     *
4230     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4231     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4232     *      mul-float, div-float, rem-float
4233     */
4234    /* binop vAA, vBB, vCC */
4235    FETCH(r0, 1)                        @ r0<- CCBB
4236    mov     r9, rINST, lsr #8           @ r9<- AA
4237    mov     r3, r0, lsr #8              @ r3<- CC
4238    and     r2, r0, #255                @ r2<- BB
4239    GET_VREG(r1, r3)                    @ r1<- vCC
4240    GET_VREG(r0, r2)                    @ r0<- vBB
4241    .if 1
4242    cmp     r1, #0                      @ is second operand zero?
4243    beq     common_errDivideByZero
4244    .endif
4245
4246    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4247                               @ optional op; may set condition codes
4248    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4249    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4250    SET_VREG(r1, r9)               @ vAA<- r1
4251    GOTO_OPCODE(ip)                     @ jump to next instruction
4252    /* 11-14 instructions */
4253
4254
4255/* ------------------------------ */
4256    .balign 64
4257.L_OP_AND_INT: /* 0x95 */
4258/* File: armv5te/OP_AND_INT.S */
4259/* File: armv5te/binop.S */
4260    /*
4261     * Generic 32-bit binary operation.  Provide an "instr" line that
4262     * specifies an instruction that performs "result = r0 op r1".
4263     * This could be an ARM instruction or a function call.  (If the result
4264     * comes back in a register other than r0, you can override "result".)
4265     *
4266     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4267     * vCC (r1).  Useful for integer division and modulus.  Note that we
4268     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4269     * handles it correctly.
4270     *
4271     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4272     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4273     *      mul-float, div-float, rem-float
4274     */
4275    /* binop vAA, vBB, vCC */
4276    FETCH(r0, 1)                        @ r0<- CCBB
4277    mov     r9, rINST, lsr #8           @ r9<- AA
4278    mov     r3, r0, lsr #8              @ r3<- CC
4279    and     r2, r0, #255                @ r2<- BB
4280    GET_VREG(r1, r3)                    @ r1<- vCC
4281    GET_VREG(r0, r2)                    @ r0<- vBB
4282    .if 0
4283    cmp     r1, #0                      @ is second operand zero?
4284    beq     common_errDivideByZero
4285    .endif
4286
4287    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4288                               @ optional op; may set condition codes
4289    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4290    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4291    SET_VREG(r0, r9)               @ vAA<- r0
4292    GOTO_OPCODE(ip)                     @ jump to next instruction
4293    /* 11-14 instructions */
4294
4295
4296/* ------------------------------ */
4297    .balign 64
4298.L_OP_OR_INT: /* 0x96 */
4299/* File: armv5te/OP_OR_INT.S */
4300/* File: armv5te/binop.S */
4301    /*
4302     * Generic 32-bit binary operation.  Provide an "instr" line that
4303     * specifies an instruction that performs "result = r0 op r1".
4304     * This could be an ARM instruction or a function call.  (If the result
4305     * comes back in a register other than r0, you can override "result".)
4306     *
4307     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4308     * vCC (r1).  Useful for integer division and modulus.  Note that we
4309     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4310     * handles it correctly.
4311     *
4312     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4313     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4314     *      mul-float, div-float, rem-float
4315     */
4316    /* binop vAA, vBB, vCC */
4317    FETCH(r0, 1)                        @ r0<- CCBB
4318    mov     r9, rINST, lsr #8           @ r9<- AA
4319    mov     r3, r0, lsr #8              @ r3<- CC
4320    and     r2, r0, #255                @ r2<- BB
4321    GET_VREG(r1, r3)                    @ r1<- vCC
4322    GET_VREG(r0, r2)                    @ r0<- vBB
4323    .if 0
4324    cmp     r1, #0                      @ is second operand zero?
4325    beq     common_errDivideByZero
4326    .endif
4327
4328    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4329                               @ optional op; may set condition codes
4330    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4331    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4332    SET_VREG(r0, r9)               @ vAA<- r0
4333    GOTO_OPCODE(ip)                     @ jump to next instruction
4334    /* 11-14 instructions */
4335
4336
4337/* ------------------------------ */
4338    .balign 64
4339.L_OP_XOR_INT: /* 0x97 */
4340/* File: armv5te/OP_XOR_INT.S */
4341/* File: armv5te/binop.S */
4342    /*
4343     * Generic 32-bit binary operation.  Provide an "instr" line that
4344     * specifies an instruction that performs "result = r0 op r1".
4345     * This could be an ARM instruction or a function call.  (If the result
4346     * comes back in a register other than r0, you can override "result".)
4347     *
4348     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4349     * vCC (r1).  Useful for integer division and modulus.  Note that we
4350     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4351     * handles it correctly.
4352     *
4353     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4354     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4355     *      mul-float, div-float, rem-float
4356     */
4357    /* binop vAA, vBB, vCC */
4358    FETCH(r0, 1)                        @ r0<- CCBB
4359    mov     r9, rINST, lsr #8           @ r9<- AA
4360    mov     r3, r0, lsr #8              @ r3<- CC
4361    and     r2, r0, #255                @ r2<- BB
4362    GET_VREG(r1, r3)                    @ r1<- vCC
4363    GET_VREG(r0, r2)                    @ r0<- vBB
4364    .if 0
4365    cmp     r1, #0                      @ is second operand zero?
4366    beq     common_errDivideByZero
4367    .endif
4368
4369    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4370                               @ optional op; may set condition codes
4371    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4372    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4373    SET_VREG(r0, r9)               @ vAA<- r0
4374    GOTO_OPCODE(ip)                     @ jump to next instruction
4375    /* 11-14 instructions */
4376
4377
4378/* ------------------------------ */
4379    .balign 64
4380.L_OP_SHL_INT: /* 0x98 */
4381/* File: armv5te/OP_SHL_INT.S */
4382/* File: armv5te/binop.S */
4383    /*
4384     * Generic 32-bit binary operation.  Provide an "instr" line that
4385     * specifies an instruction that performs "result = r0 op r1".
4386     * This could be an ARM instruction or a function call.  (If the result
4387     * comes back in a register other than r0, you can override "result".)
4388     *
4389     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4390     * vCC (r1).  Useful for integer division and modulus.  Note that we
4391     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4392     * handles it correctly.
4393     *
4394     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4395     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4396     *      mul-float, div-float, rem-float
4397     */
4398    /* binop vAA, vBB, vCC */
4399    FETCH(r0, 1)                        @ r0<- CCBB
4400    mov     r9, rINST, lsr #8           @ r9<- AA
4401    mov     r3, r0, lsr #8              @ r3<- CC
4402    and     r2, r0, #255                @ r2<- BB
4403    GET_VREG(r1, r3)                    @ r1<- vCC
4404    GET_VREG(r0, r2)                    @ r0<- vBB
4405    .if 0
4406    cmp     r1, #0                      @ is second operand zero?
4407    beq     common_errDivideByZero
4408    .endif
4409
4410    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4411    and     r1, r1, #31                           @ optional op; may set condition codes
4412    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4413    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4414    SET_VREG(r0, r9)               @ vAA<- r0
4415    GOTO_OPCODE(ip)                     @ jump to next instruction
4416    /* 11-14 instructions */
4417
4418
4419/* ------------------------------ */
4420    .balign 64
4421.L_OP_SHR_INT: /* 0x99 */
4422/* File: armv5te/OP_SHR_INT.S */
4423/* File: armv5te/binop.S */
4424    /*
4425     * Generic 32-bit binary operation.  Provide an "instr" line that
4426     * specifies an instruction that performs "result = r0 op r1".
4427     * This could be an ARM instruction or a function call.  (If the result
4428     * comes back in a register other than r0, you can override "result".)
4429     *
4430     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4431     * vCC (r1).  Useful for integer division and modulus.  Note that we
4432     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4433     * handles it correctly.
4434     *
4435     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4436     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4437     *      mul-float, div-float, rem-float
4438     */
4439    /* binop vAA, vBB, vCC */
4440    FETCH(r0, 1)                        @ r0<- CCBB
4441    mov     r9, rINST, lsr #8           @ r9<- AA
4442    mov     r3, r0, lsr #8              @ r3<- CC
4443    and     r2, r0, #255                @ r2<- BB
4444    GET_VREG(r1, r3)                    @ r1<- vCC
4445    GET_VREG(r0, r2)                    @ r0<- vBB
4446    .if 0
4447    cmp     r1, #0                      @ is second operand zero?
4448    beq     common_errDivideByZero
4449    .endif
4450
4451    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4452    and     r1, r1, #31                           @ optional op; may set condition codes
4453    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4455    SET_VREG(r0, r9)               @ vAA<- r0
4456    GOTO_OPCODE(ip)                     @ jump to next instruction
4457    /* 11-14 instructions */
4458
4459
4460/* ------------------------------ */
4461    .balign 64
4462.L_OP_USHR_INT: /* 0x9a */
4463/* File: armv5te/OP_USHR_INT.S */
4464/* File: armv5te/binop.S */
4465    /*
4466     * Generic 32-bit binary operation.  Provide an "instr" line that
4467     * specifies an instruction that performs "result = r0 op r1".
4468     * This could be an ARM instruction or a function call.  (If the result
4469     * comes back in a register other than r0, you can override "result".)
4470     *
4471     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4472     * vCC (r1).  Useful for integer division and modulus.  Note that we
4473     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4474     * handles it correctly.
4475     *
4476     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4477     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4478     *      mul-float, div-float, rem-float
4479     */
4480    /* binop vAA, vBB, vCC */
4481    FETCH(r0, 1)                        @ r0<- CCBB
4482    mov     r9, rINST, lsr #8           @ r9<- AA
4483    mov     r3, r0, lsr #8              @ r3<- CC
4484    and     r2, r0, #255                @ r2<- BB
4485    GET_VREG(r1, r3)                    @ r1<- vCC
4486    GET_VREG(r0, r2)                    @ r0<- vBB
4487    .if 0
4488    cmp     r1, #0                      @ is second operand zero?
4489    beq     common_errDivideByZero
4490    .endif
4491
4492    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4493    and     r1, r1, #31                           @ optional op; may set condition codes
4494    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4496    SET_VREG(r0, r9)               @ vAA<- r0
4497    GOTO_OPCODE(ip)                     @ jump to next instruction
4498    /* 11-14 instructions */
4499
4500
4501/* ------------------------------ */
4502    .balign 64
4503.L_OP_ADD_LONG: /* 0x9b */
4504/* File: armv5te/OP_ADD_LONG.S */
4505/* File: armv5te/binopWide.S */
4506    /*
4507     * Generic 64-bit binary operation.  Provide an "instr" line that
4508     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4509     * This could be an ARM instruction or a function call.  (If the result
4510     * comes back in a register other than r0, you can override "result".)
4511     *
4512     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4513     * vCC (r1).  Useful for integer division and modulus.
4514     *
4515     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4516     *      xor-long, add-double, sub-double, mul-double, div-double,
4517     *      rem-double
4518     *
4519     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4520     */
4521    /* binop vAA, vBB, vCC */
4522    FETCH(r0, 1)                        @ r0<- CCBB
4523    mov     r9, rINST, lsr #8           @ r9<- AA
4524    and     r2, r0, #255                @ r2<- BB
4525    mov     r3, r0, lsr #8              @ r3<- CC
4526    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4527    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4528    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4529    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4530    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4531    .if 0
4532    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4533    beq     common_errDivideByZero
4534    .endif
4535    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4536
4537    adds    r0, r0, r2                           @ optional op; may set condition codes
4538    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4539    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4540    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4541    GOTO_OPCODE(ip)                     @ jump to next instruction
4542    /* 14-17 instructions */
4543
4544
4545/* ------------------------------ */
4546    .balign 64
4547.L_OP_SUB_LONG: /* 0x9c */
4548/* File: armv5te/OP_SUB_LONG.S */
4549/* File: armv5te/binopWide.S */
4550    /*
4551     * Generic 64-bit binary operation.  Provide an "instr" line that
4552     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4553     * This could be an ARM instruction or a function call.  (If the result
4554     * comes back in a register other than r0, you can override "result".)
4555     *
4556     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4557     * vCC (r1).  Useful for integer division and modulus.
4558     *
4559     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4560     *      xor-long, add-double, sub-double, mul-double, div-double,
4561     *      rem-double
4562     *
4563     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4564     */
4565    /* binop vAA, vBB, vCC */
4566    FETCH(r0, 1)                        @ r0<- CCBB
4567    mov     r9, rINST, lsr #8           @ r9<- AA
4568    and     r2, r0, #255                @ r2<- BB
4569    mov     r3, r0, lsr #8              @ r3<- CC
4570    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4571    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4572    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4573    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4574    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4575    .if 0
4576    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4577    beq     common_errDivideByZero
4578    .endif
4579    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4580
4581    subs    r0, r0, r2                           @ optional op; may set condition codes
4582    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4584    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4585    GOTO_OPCODE(ip)                     @ jump to next instruction
4586    /* 14-17 instructions */
4587
4588
4589/* ------------------------------ */
4590    .balign 64
4591.L_OP_MUL_LONG: /* 0x9d */
4592/* File: armv5te/OP_MUL_LONG.S */
4593    /*
4594     * Signed 64-bit integer multiply.
4595     *
4596     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4597     *        WX
4598     *      x YZ
4599     *  --------
4600     *     ZW ZX
4601     *  YW YX
4602     *
4603     * The low word of the result holds ZX, the high word holds
4604     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4605     * it doesn't fit in the low 64 bits.
4606     *
4607     * Unlike most ARM math operations, multiply instructions have
4608     * restrictions on using the same register more than once (Rd and Rm
4609     * cannot be the same).
4610     */
4611    /* mul-long vAA, vBB, vCC */
4612    FETCH(r0, 1)                        @ r0<- CCBB
4613    and     r2, r0, #255                @ r2<- BB
4614    mov     r3, r0, lsr #8              @ r3<- CC
4615    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4616    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4617    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4618    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4619    mul     ip, r2, r1                  @  ip<- ZxW
4620    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4621    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4622    mov     r0, rINST, lsr #8           @ r0<- AA
4623    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4624    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4625    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4626    b       .LOP_MUL_LONG_finish
4627
4628/* ------------------------------ */
4629    .balign 64
4630.L_OP_DIV_LONG: /* 0x9e */
4631/* File: armv5te/OP_DIV_LONG.S */
4632/* File: armv5te/binopWide.S */
4633    /*
4634     * Generic 64-bit binary operation.  Provide an "instr" line that
4635     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4636     * This could be an ARM instruction or a function call.  (If the result
4637     * comes back in a register other than r0, you can override "result".)
4638     *
4639     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4640     * vCC (r1).  Useful for integer division and modulus.
4641     *
4642     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4643     *      xor-long, add-double, sub-double, mul-double, div-double,
4644     *      rem-double
4645     *
4646     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4647     */
4648    /* binop vAA, vBB, vCC */
4649    FETCH(r0, 1)                        @ r0<- CCBB
4650    mov     r9, rINST, lsr #8           @ r9<- AA
4651    and     r2, r0, #255                @ r2<- BB
4652    mov     r3, r0, lsr #8              @ r3<- CC
4653    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4654    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4655    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4656    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4657    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4658    .if 1
4659    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4660    beq     common_errDivideByZero
4661    .endif
4662    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4663
4664                               @ optional op; may set condition codes
4665    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4666    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4667    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4668    GOTO_OPCODE(ip)                     @ jump to next instruction
4669    /* 14-17 instructions */
4670
4671
4672/* ------------------------------ */
4673    .balign 64
4674.L_OP_REM_LONG: /* 0x9f */
4675/* File: armv5te/OP_REM_LONG.S */
4676/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4677/* File: armv5te/binopWide.S */
4678    /*
4679     * Generic 64-bit binary operation.  Provide an "instr" line that
4680     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4681     * This could be an ARM instruction or a function call.  (If the result
4682     * comes back in a register other than r0, you can override "result".)
4683     *
4684     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4685     * vCC (r1).  Useful for integer division and modulus.
4686     *
4687     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4688     *      xor-long, add-double, sub-double, mul-double, div-double,
4689     *      rem-double
4690     *
4691     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4692     */
4693    /* binop vAA, vBB, vCC */
4694    FETCH(r0, 1)                        @ r0<- CCBB
4695    mov     r9, rINST, lsr #8           @ r9<- AA
4696    and     r2, r0, #255                @ r2<- BB
4697    mov     r3, r0, lsr #8              @ r3<- CC
4698    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4699    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4700    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4701    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4702    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4703    .if 1
4704    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4705    beq     common_errDivideByZero
4706    .endif
4707    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4708
4709                               @ optional op; may set condition codes
4710    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4712    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4713    GOTO_OPCODE(ip)                     @ jump to next instruction
4714    /* 14-17 instructions */
4715
4716
4717/* ------------------------------ */
4718    .balign 64
4719.L_OP_AND_LONG: /* 0xa0 */
4720/* File: armv5te/OP_AND_LONG.S */
4721/* File: armv5te/binopWide.S */
4722    /*
4723     * Generic 64-bit binary operation.  Provide an "instr" line that
4724     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4725     * This could be an ARM instruction or a function call.  (If the result
4726     * comes back in a register other than r0, you can override "result".)
4727     *
4728     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4729     * vCC (r1).  Useful for integer division and modulus.
4730     *
4731     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4732     *      xor-long, add-double, sub-double, mul-double, div-double,
4733     *      rem-double
4734     *
4735     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4736     */
4737    /* binop vAA, vBB, vCC */
4738    FETCH(r0, 1)                        @ r0<- CCBB
4739    mov     r9, rINST, lsr #8           @ r9<- AA
4740    and     r2, r0, #255                @ r2<- BB
4741    mov     r3, r0, lsr #8              @ r3<- CC
4742    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4743    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4744    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4745    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4746    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4747    .if 0
4748    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4749    beq     common_errDivideByZero
4750    .endif
4751    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4752
4753    and     r0, r0, r2                           @ optional op; may set condition codes
4754    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4755    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4756    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4757    GOTO_OPCODE(ip)                     @ jump to next instruction
4758    /* 14-17 instructions */
4759
4760
4761/* ------------------------------ */
4762    .balign 64
4763.L_OP_OR_LONG: /* 0xa1 */
4764/* File: armv5te/OP_OR_LONG.S */
4765/* File: armv5te/binopWide.S */
4766    /*
4767     * Generic 64-bit binary operation.  Provide an "instr" line that
4768     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4769     * This could be an ARM instruction or a function call.  (If the result
4770     * comes back in a register other than r0, you can override "result".)
4771     *
4772     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4773     * vCC (r1).  Useful for integer division and modulus.
4774     *
4775     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4776     *      xor-long, add-double, sub-double, mul-double, div-double,
4777     *      rem-double
4778     *
4779     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4780     */
4781    /* binop vAA, vBB, vCC */
4782    FETCH(r0, 1)                        @ r0<- CCBB
4783    mov     r9, rINST, lsr #8           @ r9<- AA
4784    and     r2, r0, #255                @ r2<- BB
4785    mov     r3, r0, lsr #8              @ r3<- CC
4786    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4787    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4788    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4789    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4790    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4791    .if 0
4792    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4793    beq     common_errDivideByZero
4794    .endif
4795    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4796
4797    orr     r0, r0, r2                           @ optional op; may set condition codes
4798    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4800    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4801    GOTO_OPCODE(ip)                     @ jump to next instruction
4802    /* 14-17 instructions */
4803
4804
4805/* ------------------------------ */
4806    .balign 64
4807.L_OP_XOR_LONG: /* 0xa2 */
4808/* File: armv5te/OP_XOR_LONG.S */
4809/* File: armv5te/binopWide.S */
4810    /*
4811     * Generic 64-bit binary operation.  Provide an "instr" line that
4812     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4813     * This could be an ARM instruction or a function call.  (If the result
4814     * comes back in a register other than r0, you can override "result".)
4815     *
4816     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4817     * vCC (r1).  Useful for integer division and modulus.
4818     *
4819     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4820     *      xor-long, add-double, sub-double, mul-double, div-double,
4821     *      rem-double
4822     *
4823     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4824     */
4825    /* binop vAA, vBB, vCC */
4826    FETCH(r0, 1)                        @ r0<- CCBB
4827    mov     r9, rINST, lsr #8           @ r9<- AA
4828    and     r2, r0, #255                @ r2<- BB
4829    mov     r3, r0, lsr #8              @ r3<- CC
4830    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4831    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4832    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4833    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4834    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4835    .if 0
4836    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4837    beq     common_errDivideByZero
4838    .endif
4839    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4840
4841    eor     r0, r0, r2                           @ optional op; may set condition codes
4842    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4843    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4844    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4845    GOTO_OPCODE(ip)                     @ jump to next instruction
4846    /* 14-17 instructions */
4847
4848
4849/* ------------------------------ */
4850    .balign 64
4851.L_OP_SHL_LONG: /* 0xa3 */
4852/* File: armv5te/OP_SHL_LONG.S */
4853    /*
4854     * Long integer shift.  This is different from the generic 32/64-bit
4855     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4856     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4857     * 6 bits of the shift distance.
4858     */
4859    /* shl-long vAA, vBB, vCC */
4860    FETCH(r0, 1)                        @ r0<- CCBB
4861    mov     r9, rINST, lsr #8           @ r9<- AA
4862    and     r3, r0, #255                @ r3<- BB
4863    mov     r0, r0, lsr #8              @ r0<- CC
4864    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4865    GET_VREG(r2, r0)                    @ r2<- vCC
4866    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4867    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4868    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4869
4870    mov     r1, r1, asl r2              @  r1<- r1 << r2
4871    rsb     r3, r2, #32                 @  r3<- 32 - r2
4872    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
4873    subs    ip, r2, #32                 @  ip<- r2 - 32
4874    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
4875    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4876    b       .LOP_SHL_LONG_finish
4877
4878/* ------------------------------ */
4879    .balign 64
4880.L_OP_SHR_LONG: /* 0xa4 */
4881/* File: armv5te/OP_SHR_LONG.S */
4882    /*
4883     * Long integer shift.  This is different from the generic 32/64-bit
4884     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4885     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4886     * 6 bits of the shift distance.
4887     */
4888    /* shr-long vAA, vBB, vCC */
4889    FETCH(r0, 1)                        @ r0<- CCBB
4890    mov     r9, rINST, lsr #8           @ r9<- AA
4891    and     r3, r0, #255                @ r3<- BB
4892    mov     r0, r0, lsr #8              @ r0<- CC
4893    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4894    GET_VREG(r2, r0)                    @ r2<- vCC
4895    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4896    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4897    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4898
4899    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4900    rsb     r3, r2, #32                 @  r3<- 32 - r2
4901    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4902    subs    ip, r2, #32                 @  ip<- r2 - 32
4903    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
4904    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4905    b       .LOP_SHR_LONG_finish
4906
4907/* ------------------------------ */
4908    .balign 64
4909.L_OP_USHR_LONG: /* 0xa5 */
4910/* File: armv5te/OP_USHR_LONG.S */
4911    /*
4912     * Long integer shift.  This is different from the generic 32/64-bit
4913     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4914     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4915     * 6 bits of the shift distance.
4916     */
4917    /* ushr-long vAA, vBB, vCC */
4918    FETCH(r0, 1)                        @ r0<- CCBB
4919    mov     r9, rINST, lsr #8           @ r9<- AA
4920    and     r3, r0, #255                @ r3<- BB
4921    mov     r0, r0, lsr #8              @ r0<- CC
4922    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4923    GET_VREG(r2, r0)                    @ r2<- vCC
4924    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4925    and     r2, r2, #63                 @ r0<- r0 & 0x3f
4926    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4927
4928    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
4929    rsb     r3, r2, #32                 @  r3<- 32 - r2
4930    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
4931    subs    ip, r2, #32                 @  ip<- r2 - 32
4932    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
4933    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4934    b       .LOP_USHR_LONG_finish
4935
4936/* ------------------------------ */
4937    .balign 64
4938.L_OP_ADD_FLOAT: /* 0xa6 */
4939/* File: arm-vfp/OP_ADD_FLOAT.S */
4940/* File: arm-vfp/fbinop.S */
4941    /*
4942     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4943     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4944     * use the "softfp" ABI, this must be an instruction, not a function call.
4945     *
4946     * For: add-float, sub-float, mul-float, div-float
4947     */
4948    /* floatop vAA, vBB, vCC */
4949    FETCH(r0, 1)                        @ r0<- CCBB
4950    mov     r9, rINST, lsr #8           @ r9<- AA
4951    mov     r3, r0, lsr #8              @ r3<- CC
4952    and     r2, r0, #255                @ r2<- BB
4953    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4954    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4955    flds    s1, [r3]                    @ s1<- vCC
4956    flds    s0, [r2]                    @ s0<- vBB
4957
4958    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4959    fadds   s2, s0, s1                              @ s2<- op
4960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4961    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4962    fsts    s2, [r9]                    @ vAA<- s2
4963    GOTO_OPCODE(ip)                     @ jump to next instruction
4964
4965
4966/* ------------------------------ */
4967    .balign 64
4968.L_OP_SUB_FLOAT: /* 0xa7 */
4969/* File: arm-vfp/OP_SUB_FLOAT.S */
4970/* File: arm-vfp/fbinop.S */
4971    /*
4972     * Generic 32-bit floating-point operation.  Provide an "instr" line that
4973     * specifies an instruction that performs "s2 = s0 op s1".  Because we
4974     * use the "softfp" ABI, this must be an instruction, not a function call.
4975     *
4976     * For: add-float, sub-float, mul-float, div-float
4977     */
4978    /* floatop vAA, vBB, vCC */
4979    FETCH(r0, 1)                        @ r0<- CCBB
4980    mov     r9, rINST, lsr #8           @ r9<- AA
4981    mov     r3, r0, lsr #8              @ r3<- CC
4982    and     r2, r0, #255                @ r2<- BB
4983    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
4984    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
4985    flds    s1, [r3]                    @ s1<- vCC
4986    flds    s0, [r2]                    @ s0<- vBB
4987
4988    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4989    fsubs   s2, s0, s1                              @ s2<- op
4990    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4991    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
4992    fsts    s2, [r9]                    @ vAA<- s2
4993    GOTO_OPCODE(ip)                     @ jump to next instruction
4994
4995
4996/* ------------------------------ */
4997    .balign 64
4998.L_OP_MUL_FLOAT: /* 0xa8 */
4999/* File: arm-vfp/OP_MUL_FLOAT.S */
5000/* File: arm-vfp/fbinop.S */
5001    /*
5002     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5003     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5004     * use the "softfp" ABI, this must be an instruction, not a function call.
5005     *
5006     * For: add-float, sub-float, mul-float, div-float
5007     */
5008    /* floatop vAA, vBB, vCC */
5009    FETCH(r0, 1)                        @ r0<- CCBB
5010    mov     r9, rINST, lsr #8           @ r9<- AA
5011    mov     r3, r0, lsr #8              @ r3<- CC
5012    and     r2, r0, #255                @ r2<- BB
5013    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5014    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5015    flds    s1, [r3]                    @ s1<- vCC
5016    flds    s0, [r2]                    @ s0<- vBB
5017
5018    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5019    fmuls   s2, s0, s1                              @ s2<- op
5020    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5021    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5022    fsts    s2, [r9]                    @ vAA<- s2
5023    GOTO_OPCODE(ip)                     @ jump to next instruction
5024
5025
5026/* ------------------------------ */
5027    .balign 64
5028.L_OP_DIV_FLOAT: /* 0xa9 */
5029/* File: arm-vfp/OP_DIV_FLOAT.S */
5030/* File: arm-vfp/fbinop.S */
5031    /*
5032     * Generic 32-bit floating-point operation.  Provide an "instr" line that
5033     * specifies an instruction that performs "s2 = s0 op s1".  Because we
5034     * use the "softfp" ABI, this must be an instruction, not a function call.
5035     *
5036     * For: add-float, sub-float, mul-float, div-float
5037     */
5038    /* floatop vAA, vBB, vCC */
5039    FETCH(r0, 1)                        @ r0<- CCBB
5040    mov     r9, rINST, lsr #8           @ r9<- AA
5041    mov     r3, r0, lsr #8              @ r3<- CC
5042    and     r2, r0, #255                @ r2<- BB
5043    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5044    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5045    flds    s1, [r3]                    @ s1<- vCC
5046    flds    s0, [r2]                    @ s0<- vBB
5047
5048    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5049    fdivs   s2, s0, s1                              @ s2<- op
5050    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5051    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5052    fsts    s2, [r9]                    @ vAA<- s2
5053    GOTO_OPCODE(ip)                     @ jump to next instruction
5054
5055
5056/* ------------------------------ */
5057    .balign 64
5058.L_OP_REM_FLOAT: /* 0xaa */
5059/* File: armv5te/OP_REM_FLOAT.S */
5060/* EABI doesn't define a float remainder function, but libm does */
5061/* File: armv5te/binop.S */
5062    /*
5063     * Generic 32-bit binary operation.  Provide an "instr" line that
5064     * specifies an instruction that performs "result = r0 op r1".
5065     * This could be an ARM instruction or a function call.  (If the result
5066     * comes back in a register other than r0, you can override "result".)
5067     *
5068     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5069     * vCC (r1).  Useful for integer division and modulus.  Note that we
5070     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5071     * handles it correctly.
5072     *
5073     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5074     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5075     *      mul-float, div-float, rem-float
5076     */
5077    /* binop vAA, vBB, vCC */
5078    FETCH(r0, 1)                        @ r0<- CCBB
5079    mov     r9, rINST, lsr #8           @ r9<- AA
5080    mov     r3, r0, lsr #8              @ r3<- CC
5081    and     r2, r0, #255                @ r2<- BB
5082    GET_VREG(r1, r3)                    @ r1<- vCC
5083    GET_VREG(r0, r2)                    @ r0<- vBB
5084    .if 0
5085    cmp     r1, #0                      @ is second operand zero?
5086    beq     common_errDivideByZero
5087    .endif
5088
5089    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5090                               @ optional op; may set condition codes
5091    bl      fmodf                              @ r0<- op, r0-r3 changed
5092    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5093    SET_VREG(r0, r9)               @ vAA<- r0
5094    GOTO_OPCODE(ip)                     @ jump to next instruction
5095    /* 11-14 instructions */
5096
5097
5098/* ------------------------------ */
5099    .balign 64
5100.L_OP_ADD_DOUBLE: /* 0xab */
5101/* File: arm-vfp/OP_ADD_DOUBLE.S */
5102/* File: arm-vfp/fbinopWide.S */
5103    /*
5104     * Generic 64-bit double-precision floating point binary operation.
5105     * Provide an "instr" line that specifies an instruction that performs
5106     * "d2 = d0 op d1".
5107     *
5108     * for: add-double, sub-double, mul-double, div-double
5109     */
5110    /* doubleop vAA, vBB, vCC */
5111    FETCH(r0, 1)                        @ r0<- CCBB
5112    mov     r9, rINST, lsr #8           @ r9<- AA
5113    mov     r3, r0, lsr #8              @ r3<- CC
5114    and     r2, r0, #255                @ r2<- BB
5115    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5116    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5117    fldd    d1, [r3]                    @ d1<- vCC
5118    fldd    d0, [r2]                    @ d0<- vBB
5119
5120    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5121    faddd   d2, d0, d1                              @ s2<- op
5122    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5123    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5124    fstd    d2, [r9]                    @ vAA<- d2
5125    GOTO_OPCODE(ip)                     @ jump to next instruction
5126
5127
5128/* ------------------------------ */
5129    .balign 64
5130.L_OP_SUB_DOUBLE: /* 0xac */
5131/* File: arm-vfp/OP_SUB_DOUBLE.S */
5132/* File: arm-vfp/fbinopWide.S */
5133    /*
5134     * Generic 64-bit double-precision floating point binary operation.
5135     * Provide an "instr" line that specifies an instruction that performs
5136     * "d2 = d0 op d1".
5137     *
5138     * for: add-double, sub-double, mul-double, div-double
5139     */
5140    /* doubleop vAA, vBB, vCC */
5141    FETCH(r0, 1)                        @ r0<- CCBB
5142    mov     r9, rINST, lsr #8           @ r9<- AA
5143    mov     r3, r0, lsr #8              @ r3<- CC
5144    and     r2, r0, #255                @ r2<- BB
5145    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5146    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5147    fldd    d1, [r3]                    @ d1<- vCC
5148    fldd    d0, [r2]                    @ d0<- vBB
5149
5150    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5151    fsubd   d2, d0, d1                              @ s2<- op
5152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5153    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5154    fstd    d2, [r9]                    @ vAA<- d2
5155    GOTO_OPCODE(ip)                     @ jump to next instruction
5156
5157
5158/* ------------------------------ */
5159    .balign 64
5160.L_OP_MUL_DOUBLE: /* 0xad */
5161/* File: arm-vfp/OP_MUL_DOUBLE.S */
5162/* File: arm-vfp/fbinopWide.S */
5163    /*
5164     * Generic 64-bit double-precision floating point binary operation.
5165     * Provide an "instr" line that specifies an instruction that performs
5166     * "d2 = d0 op d1".
5167     *
5168     * for: add-double, sub-double, mul-double, div-double
5169     */
5170    /* doubleop vAA, vBB, vCC */
5171    FETCH(r0, 1)                        @ r0<- CCBB
5172    mov     r9, rINST, lsr #8           @ r9<- AA
5173    mov     r3, r0, lsr #8              @ r3<- CC
5174    and     r2, r0, #255                @ r2<- BB
5175    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5176    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5177    fldd    d1, [r3]                    @ d1<- vCC
5178    fldd    d0, [r2]                    @ d0<- vBB
5179
5180    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5181    fmuld   d2, d0, d1                              @ s2<- op
5182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5183    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5184    fstd    d2, [r9]                    @ vAA<- d2
5185    GOTO_OPCODE(ip)                     @ jump to next instruction
5186
5187
5188/* ------------------------------ */
5189    .balign 64
5190.L_OP_DIV_DOUBLE: /* 0xae */
5191/* File: arm-vfp/OP_DIV_DOUBLE.S */
5192/* File: arm-vfp/fbinopWide.S */
5193    /*
5194     * Generic 64-bit double-precision floating point binary operation.
5195     * Provide an "instr" line that specifies an instruction that performs
5196     * "d2 = d0 op d1".
5197     *
5198     * for: add-double, sub-double, mul-double, div-double
5199     */
5200    /* doubleop vAA, vBB, vCC */
5201    FETCH(r0, 1)                        @ r0<- CCBB
5202    mov     r9, rINST, lsr #8           @ r9<- AA
5203    mov     r3, r0, lsr #8              @ r3<- CC
5204    and     r2, r0, #255                @ r2<- BB
5205    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vCC
5206    VREG_INDEX_TO_ADDR(r2, r2)          @ r2<- &vBB
5207    fldd    d1, [r3]                    @ d1<- vCC
5208    fldd    d0, [r2]                    @ d0<- vBB
5209
5210    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5211    fdivd   d2, d0, d1                              @ s2<- op
5212    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5213    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vAA
5214    fstd    d2, [r9]                    @ vAA<- d2
5215    GOTO_OPCODE(ip)                     @ jump to next instruction
5216
5217
5218/* ------------------------------ */
5219    .balign 64
5220.L_OP_REM_DOUBLE: /* 0xaf */
5221/* File: armv5te/OP_REM_DOUBLE.S */
5222/* EABI doesn't define a double remainder function, but libm does */
5223/* File: armv5te/binopWide.S */
5224    /*
5225     * Generic 64-bit binary operation.  Provide an "instr" line that
5226     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5227     * This could be an ARM instruction or a function call.  (If the result
5228     * comes back in a register other than r0, you can override "result".)
5229     *
5230     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5231     * vCC (r1).  Useful for integer division and modulus.
5232     *
5233     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5234     *      xor-long, add-double, sub-double, mul-double, div-double,
5235     *      rem-double
5236     *
5237     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5238     */
5239    /* binop vAA, vBB, vCC */
5240    FETCH(r0, 1)                        @ r0<- CCBB
5241    mov     r9, rINST, lsr #8           @ r9<- AA
5242    and     r2, r0, #255                @ r2<- BB
5243    mov     r3, r0, lsr #8              @ r3<- CC
5244    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5245    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5246    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5247    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5248    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5249    .if 0
5250    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5251    beq     common_errDivideByZero
5252    .endif
5253    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5254
5255                               @ optional op; may set condition codes
5256    bl      fmod                              @ result<- op, r0-r3 changed
5257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5258    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5259    GOTO_OPCODE(ip)                     @ jump to next instruction
5260    /* 14-17 instructions */
5261
5262
5263/* ------------------------------ */
5264    .balign 64
5265.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5266/* File: armv5te/OP_ADD_INT_2ADDR.S */
5267/* File: armv5te/binop2addr.S */
5268    /*
5269     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5270     * that specifies an instruction that performs "result = r0 op r1".
5271     * This could be an ARM instruction or a function call.  (If the result
5272     * comes back in a register other than r0, you can override "result".)
5273     *
5274     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5275     * vCC (r1).  Useful for integer division and modulus.
5276     *
5277     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5278     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5279     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5280     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5281     */
5282    /* binop/2addr vA, vB */
5283    mov     r9, rINST, lsr #8           @ r9<- A+
5284    mov     r3, rINST, lsr #12          @ r3<- B
5285    and     r9, r9, #15
5286    GET_VREG(r1, r3)                    @ r1<- vB
5287    GET_VREG(r0, r9)                    @ r0<- vA
5288    .if 0
5289    cmp     r1, #0                      @ is second operand zero?
5290    beq     common_errDivideByZero
5291    .endif
5292    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5293
5294                               @ optional op; may set condition codes
5295    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5296    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5297    SET_VREG(r0, r9)               @ vAA<- r0
5298    GOTO_OPCODE(ip)                     @ jump to next instruction
5299    /* 10-13 instructions */
5300
5301
5302/* ------------------------------ */
5303    .balign 64
5304.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5305/* File: armv5te/OP_SUB_INT_2ADDR.S */
5306/* File: armv5te/binop2addr.S */
5307    /*
5308     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5309     * that specifies an instruction that performs "result = r0 op r1".
5310     * This could be an ARM instruction or a function call.  (If the result
5311     * comes back in a register other than r0, you can override "result".)
5312     *
5313     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5314     * vCC (r1).  Useful for integer division and modulus.
5315     *
5316     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5317     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5318     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5319     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5320     */
5321    /* binop/2addr vA, vB */
5322    mov     r9, rINST, lsr #8           @ r9<- A+
5323    mov     r3, rINST, lsr #12          @ r3<- B
5324    and     r9, r9, #15
5325    GET_VREG(r1, r3)                    @ r1<- vB
5326    GET_VREG(r0, r9)                    @ r0<- vA
5327    .if 0
5328    cmp     r1, #0                      @ is second operand zero?
5329    beq     common_errDivideByZero
5330    .endif
5331    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5332
5333                               @ optional op; may set condition codes
5334    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5336    SET_VREG(r0, r9)               @ vAA<- r0
5337    GOTO_OPCODE(ip)                     @ jump to next instruction
5338    /* 10-13 instructions */
5339
5340
5341/* ------------------------------ */
5342    .balign 64
5343.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5344/* File: armv5te/OP_MUL_INT_2ADDR.S */
5345/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5346/* File: armv5te/binop2addr.S */
5347    /*
5348     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5349     * that specifies an instruction that performs "result = r0 op r1".
5350     * This could be an ARM instruction or a function call.  (If the result
5351     * comes back in a register other than r0, you can override "result".)
5352     *
5353     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5354     * vCC (r1).  Useful for integer division and modulus.
5355     *
5356     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5357     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5358     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5359     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5360     */
5361    /* binop/2addr vA, vB */
5362    mov     r9, rINST, lsr #8           @ r9<- A+
5363    mov     r3, rINST, lsr #12          @ r3<- B
5364    and     r9, r9, #15
5365    GET_VREG(r1, r3)                    @ r1<- vB
5366    GET_VREG(r0, r9)                    @ r0<- vA
5367    .if 0
5368    cmp     r1, #0                      @ is second operand zero?
5369    beq     common_errDivideByZero
5370    .endif
5371    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5372
5373                               @ optional op; may set condition codes
5374    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5375    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5376    SET_VREG(r0, r9)               @ vAA<- r0
5377    GOTO_OPCODE(ip)                     @ jump to next instruction
5378    /* 10-13 instructions */
5379
5380
5381/* ------------------------------ */
5382    .balign 64
5383.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5384/* File: armv5te/OP_DIV_INT_2ADDR.S */
5385/* File: armv5te/binop2addr.S */
5386    /*
5387     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5388     * that specifies an instruction that performs "result = r0 op r1".
5389     * This could be an ARM instruction or a function call.  (If the result
5390     * comes back in a register other than r0, you can override "result".)
5391     *
5392     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5393     * vCC (r1).  Useful for integer division and modulus.
5394     *
5395     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5396     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5397     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5398     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5399     */
5400    /* binop/2addr vA, vB */
5401    mov     r9, rINST, lsr #8           @ r9<- A+
5402    mov     r3, rINST, lsr #12          @ r3<- B
5403    and     r9, r9, #15
5404    GET_VREG(r1, r3)                    @ r1<- vB
5405    GET_VREG(r0, r9)                    @ r0<- vA
5406    .if 1
5407    cmp     r1, #0                      @ is second operand zero?
5408    beq     common_errDivideByZero
5409    .endif
5410    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5411
5412                               @ optional op; may set condition codes
5413    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5415    SET_VREG(r0, r9)               @ vAA<- r0
5416    GOTO_OPCODE(ip)                     @ jump to next instruction
5417    /* 10-13 instructions */
5418
5419
5420/* ------------------------------ */
5421    .balign 64
5422.L_OP_REM_INT_2ADDR: /* 0xb4 */
5423/* File: armv5te/OP_REM_INT_2ADDR.S */
5424/* idivmod returns quotient in r0 and remainder in r1 */
5425/* File: armv5te/binop2addr.S */
5426    /*
5427     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5428     * that specifies an instruction that performs "result = r0 op r1".
5429     * This could be an ARM instruction or a function call.  (If the result
5430     * comes back in a register other than r0, you can override "result".)
5431     *
5432     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5433     * vCC (r1).  Useful for integer division and modulus.
5434     *
5435     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5436     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5437     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5438     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5439     */
5440    /* binop/2addr vA, vB */
5441    mov     r9, rINST, lsr #8           @ r9<- A+
5442    mov     r3, rINST, lsr #12          @ r3<- B
5443    and     r9, r9, #15
5444    GET_VREG(r1, r3)                    @ r1<- vB
5445    GET_VREG(r0, r9)                    @ r0<- vA
5446    .if 1
5447    cmp     r1, #0                      @ is second operand zero?
5448    beq     common_errDivideByZero
5449    .endif
5450    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5451
5452                               @ optional op; may set condition codes
5453    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5454    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5455    SET_VREG(r1, r9)               @ vAA<- r1
5456    GOTO_OPCODE(ip)                     @ jump to next instruction
5457    /* 10-13 instructions */
5458
5459
5460/* ------------------------------ */
5461    .balign 64
5462.L_OP_AND_INT_2ADDR: /* 0xb5 */
5463/* File: armv5te/OP_AND_INT_2ADDR.S */
5464/* File: armv5te/binop2addr.S */
5465    /*
5466     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5467     * that specifies an instruction that performs "result = r0 op r1".
5468     * This could be an ARM instruction or a function call.  (If the result
5469     * comes back in a register other than r0, you can override "result".)
5470     *
5471     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5472     * vCC (r1).  Useful for integer division and modulus.
5473     *
5474     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5475     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5476     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5477     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5478     */
5479    /* binop/2addr vA, vB */
5480    mov     r9, rINST, lsr #8           @ r9<- A+
5481    mov     r3, rINST, lsr #12          @ r3<- B
5482    and     r9, r9, #15
5483    GET_VREG(r1, r3)                    @ r1<- vB
5484    GET_VREG(r0, r9)                    @ r0<- vA
5485    .if 0
5486    cmp     r1, #0                      @ is second operand zero?
5487    beq     common_errDivideByZero
5488    .endif
5489    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5490
5491                               @ optional op; may set condition codes
5492    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5493    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5494    SET_VREG(r0, r9)               @ vAA<- r0
5495    GOTO_OPCODE(ip)                     @ jump to next instruction
5496    /* 10-13 instructions */
5497
5498
5499/* ------------------------------ */
5500    .balign 64
5501.L_OP_OR_INT_2ADDR: /* 0xb6 */
5502/* File: armv5te/OP_OR_INT_2ADDR.S */
5503/* File: armv5te/binop2addr.S */
5504    /*
5505     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5506     * that specifies an instruction that performs "result = r0 op r1".
5507     * This could be an ARM instruction or a function call.  (If the result
5508     * comes back in a register other than r0, you can override "result".)
5509     *
5510     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5511     * vCC (r1).  Useful for integer division and modulus.
5512     *
5513     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5514     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5515     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5516     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5517     */
5518    /* binop/2addr vA, vB */
5519    mov     r9, rINST, lsr #8           @ r9<- A+
5520    mov     r3, rINST, lsr #12          @ r3<- B
5521    and     r9, r9, #15
5522    GET_VREG(r1, r3)                    @ r1<- vB
5523    GET_VREG(r0, r9)                    @ r0<- vA
5524    .if 0
5525    cmp     r1, #0                      @ is second operand zero?
5526    beq     common_errDivideByZero
5527    .endif
5528    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5529
5530                               @ optional op; may set condition codes
5531    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5532    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5533    SET_VREG(r0, r9)               @ vAA<- r0
5534    GOTO_OPCODE(ip)                     @ jump to next instruction
5535    /* 10-13 instructions */
5536
5537
5538/* ------------------------------ */
5539    .balign 64
5540.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5541/* File: armv5te/OP_XOR_INT_2ADDR.S */
5542/* File: armv5te/binop2addr.S */
5543    /*
5544     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5545     * that specifies an instruction that performs "result = r0 op r1".
5546     * This could be an ARM instruction or a function call.  (If the result
5547     * comes back in a register other than r0, you can override "result".)
5548     *
5549     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5550     * vCC (r1).  Useful for integer division and modulus.
5551     *
5552     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5553     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5554     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5555     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5556     */
5557    /* binop/2addr vA, vB */
5558    mov     r9, rINST, lsr #8           @ r9<- A+
5559    mov     r3, rINST, lsr #12          @ r3<- B
5560    and     r9, r9, #15
5561    GET_VREG(r1, r3)                    @ r1<- vB
5562    GET_VREG(r0, r9)                    @ r0<- vA
5563    .if 0
5564    cmp     r1, #0                      @ is second operand zero?
5565    beq     common_errDivideByZero
5566    .endif
5567    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5568
5569                               @ optional op; may set condition codes
5570    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5571    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5572    SET_VREG(r0, r9)               @ vAA<- r0
5573    GOTO_OPCODE(ip)                     @ jump to next instruction
5574    /* 10-13 instructions */
5575
5576
5577/* ------------------------------ */
5578    .balign 64
5579.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5580/* File: armv5te/OP_SHL_INT_2ADDR.S */
5581/* File: armv5te/binop2addr.S */
5582    /*
5583     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5584     * that specifies an instruction that performs "result = r0 op r1".
5585     * This could be an ARM instruction or a function call.  (If the result
5586     * comes back in a register other than r0, you can override "result".)
5587     *
5588     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5589     * vCC (r1).  Useful for integer division and modulus.
5590     *
5591     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5592     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5593     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5594     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5595     */
5596    /* binop/2addr vA, vB */
5597    mov     r9, rINST, lsr #8           @ r9<- A+
5598    mov     r3, rINST, lsr #12          @ r3<- B
5599    and     r9, r9, #15
5600    GET_VREG(r1, r3)                    @ r1<- vB
5601    GET_VREG(r0, r9)                    @ r0<- vA
5602    .if 0
5603    cmp     r1, #0                      @ is second operand zero?
5604    beq     common_errDivideByZero
5605    .endif
5606    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5607
5608    and     r1, r1, #31                           @ optional op; may set condition codes
5609    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5610    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5611    SET_VREG(r0, r9)               @ vAA<- r0
5612    GOTO_OPCODE(ip)                     @ jump to next instruction
5613    /* 10-13 instructions */
5614
5615
5616/* ------------------------------ */
5617    .balign 64
5618.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5619/* File: armv5te/OP_SHR_INT_2ADDR.S */
5620/* File: armv5te/binop2addr.S */
5621    /*
5622     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5623     * that specifies an instruction that performs "result = r0 op r1".
5624     * This could be an ARM instruction or a function call.  (If the result
5625     * comes back in a register other than r0, you can override "result".)
5626     *
5627     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5628     * vCC (r1).  Useful for integer division and modulus.
5629     *
5630     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5631     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5632     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5633     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5634     */
5635    /* binop/2addr vA, vB */
5636    mov     r9, rINST, lsr #8           @ r9<- A+
5637    mov     r3, rINST, lsr #12          @ r3<- B
5638    and     r9, r9, #15
5639    GET_VREG(r1, r3)                    @ r1<- vB
5640    GET_VREG(r0, r9)                    @ r0<- vA
5641    .if 0
5642    cmp     r1, #0                      @ is second operand zero?
5643    beq     common_errDivideByZero
5644    .endif
5645    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5646
5647    and     r1, r1, #31                           @ optional op; may set condition codes
5648    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5650    SET_VREG(r0, r9)               @ vAA<- r0
5651    GOTO_OPCODE(ip)                     @ jump to next instruction
5652    /* 10-13 instructions */
5653
5654
5655/* ------------------------------ */
5656    .balign 64
5657.L_OP_USHR_INT_2ADDR: /* 0xba */
5658/* File: armv5te/OP_USHR_INT_2ADDR.S */
5659/* File: armv5te/binop2addr.S */
5660    /*
5661     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5662     * that specifies an instruction that performs "result = r0 op r1".
5663     * This could be an ARM instruction or a function call.  (If the result
5664     * comes back in a register other than r0, you can override "result".)
5665     *
5666     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5667     * vCC (r1).  Useful for integer division and modulus.
5668     *
5669     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5670     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5671     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5672     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5673     */
5674    /* binop/2addr vA, vB */
5675    mov     r9, rINST, lsr #8           @ r9<- A+
5676    mov     r3, rINST, lsr #12          @ r3<- B
5677    and     r9, r9, #15
5678    GET_VREG(r1, r3)                    @ r1<- vB
5679    GET_VREG(r0, r9)                    @ r0<- vA
5680    .if 0
5681    cmp     r1, #0                      @ is second operand zero?
5682    beq     common_errDivideByZero
5683    .endif
5684    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5685
5686    and     r1, r1, #31                           @ optional op; may set condition codes
5687    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5688    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5689    SET_VREG(r0, r9)               @ vAA<- r0
5690    GOTO_OPCODE(ip)                     @ jump to next instruction
5691    /* 10-13 instructions */
5692
5693
5694/* ------------------------------ */
5695    .balign 64
5696.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5697/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5698/* File: armv5te/binopWide2addr.S */
5699    /*
5700     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5701     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5702     * This could be an ARM instruction or a function call.  (If the result
5703     * comes back in a register other than r0, you can override "result".)
5704     *
5705     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5706     * vCC (r1).  Useful for integer division and modulus.
5707     *
5708     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5709     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5710     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5711     *      rem-double/2addr
5712     */
5713    /* binop/2addr vA, vB */
5714    mov     r9, rINST, lsr #8           @ r9<- A+
5715    mov     r1, rINST, lsr #12          @ r1<- B
5716    and     r9, r9, #15
5717    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5718    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5719    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5720    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5721    .if 0
5722    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5723    beq     common_errDivideByZero
5724    .endif
5725    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5726
5727    adds    r0, r0, r2                           @ optional op; may set condition codes
5728    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5729    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5730    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5731    GOTO_OPCODE(ip)                     @ jump to next instruction
5732    /* 12-15 instructions */
5733
5734
5735/* ------------------------------ */
5736    .balign 64
5737.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5738/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5739/* File: armv5te/binopWide2addr.S */
5740    /*
5741     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5742     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5743     * This could be an ARM instruction or a function call.  (If the result
5744     * comes back in a register other than r0, you can override "result".)
5745     *
5746     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5747     * vCC (r1).  Useful for integer division and modulus.
5748     *
5749     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5750     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5751     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5752     *      rem-double/2addr
5753     */
5754    /* binop/2addr vA, vB */
5755    mov     r9, rINST, lsr #8           @ r9<- A+
5756    mov     r1, rINST, lsr #12          @ r1<- B
5757    and     r9, r9, #15
5758    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5759    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5760    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5761    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5762    .if 0
5763    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5764    beq     common_errDivideByZero
5765    .endif
5766    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5767
5768    subs    r0, r0, r2                           @ optional op; may set condition codes
5769    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5770    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5771    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5772    GOTO_OPCODE(ip)                     @ jump to next instruction
5773    /* 12-15 instructions */
5774
5775
5776/* ------------------------------ */
5777    .balign 64
5778.L_OP_MUL_LONG_2ADDR: /* 0xbd */
5779/* File: armv5te/OP_MUL_LONG_2ADDR.S */
5780    /*
5781     * Signed 64-bit integer multiply, "/2addr" version.
5782     *
5783     * See OP_MUL_LONG for an explanation.
5784     *
5785     * We get a little tight on registers, so to avoid looking up &fp[A]
5786     * again we stuff it into rINST.
5787     */
5788    /* mul-long/2addr vA, vB */
5789    mov     r9, rINST, lsr #8           @ r9<- A+
5790    mov     r1, rINST, lsr #12          @ r1<- B
5791    and     r9, r9, #15
5792    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5793    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
5794    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5795    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
5796    mul     ip, r2, r1                  @  ip<- ZxW
5797    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
5798    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
5799    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
5800    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5801    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
5802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5803    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
5804    GOTO_OPCODE(ip)                     @ jump to next instruction
5805
5806/* ------------------------------ */
5807    .balign 64
5808.L_OP_DIV_LONG_2ADDR: /* 0xbe */
5809/* File: armv5te/OP_DIV_LONG_2ADDR.S */
5810/* File: armv5te/binopWide2addr.S */
5811    /*
5812     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5813     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5814     * This could be an ARM instruction or a function call.  (If the result
5815     * comes back in a register other than r0, you can override "result".)
5816     *
5817     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5818     * vCC (r1).  Useful for integer division and modulus.
5819     *
5820     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5821     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5822     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5823     *      rem-double/2addr
5824     */
5825    /* binop/2addr vA, vB */
5826    mov     r9, rINST, lsr #8           @ r9<- A+
5827    mov     r1, rINST, lsr #12          @ r1<- B
5828    and     r9, r9, #15
5829    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5830    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5831    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5832    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5833    .if 1
5834    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5835    beq     common_errDivideByZero
5836    .endif
5837    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5838
5839                               @ optional op; may set condition codes
5840    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5841    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5842    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5843    GOTO_OPCODE(ip)                     @ jump to next instruction
5844    /* 12-15 instructions */
5845
5846
5847/* ------------------------------ */
5848    .balign 64
5849.L_OP_REM_LONG_2ADDR: /* 0xbf */
5850/* File: armv5te/OP_REM_LONG_2ADDR.S */
5851/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
5852/* File: armv5te/binopWide2addr.S */
5853    /*
5854     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5855     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5856     * This could be an ARM instruction or a function call.  (If the result
5857     * comes back in a register other than r0, you can override "result".)
5858     *
5859     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5860     * vCC (r1).  Useful for integer division and modulus.
5861     *
5862     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5863     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5864     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5865     *      rem-double/2addr
5866     */
5867    /* binop/2addr vA, vB */
5868    mov     r9, rINST, lsr #8           @ r9<- A+
5869    mov     r1, rINST, lsr #12          @ r1<- B
5870    and     r9, r9, #15
5871    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5872    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5873    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5874    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5875    .if 1
5876    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5877    beq     common_errDivideByZero
5878    .endif
5879    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5880
5881                               @ optional op; may set condition codes
5882    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
5883    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5884    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
5885    GOTO_OPCODE(ip)                     @ jump to next instruction
5886    /* 12-15 instructions */
5887
5888
5889/* ------------------------------ */
5890    .balign 64
5891.L_OP_AND_LONG_2ADDR: /* 0xc0 */
5892/* File: armv5te/OP_AND_LONG_2ADDR.S */
5893/* File: armv5te/binopWide2addr.S */
5894    /*
5895     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5896     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5897     * This could be an ARM instruction or a function call.  (If the result
5898     * comes back in a register other than r0, you can override "result".)
5899     *
5900     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5901     * vCC (r1).  Useful for integer division and modulus.
5902     *
5903     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5904     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5905     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5906     *      rem-double/2addr
5907     */
5908    /* binop/2addr vA, vB */
5909    mov     r9, rINST, lsr #8           @ r9<- A+
5910    mov     r1, rINST, lsr #12          @ r1<- B
5911    and     r9, r9, #15
5912    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5913    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5914    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5915    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5916    .if 0
5917    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5918    beq     common_errDivideByZero
5919    .endif
5920    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5921
5922    and     r0, r0, r2                           @ optional op; may set condition codes
5923    and     r1, r1, r3                              @ result<- op, r0-r3 changed
5924    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5925    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5926    GOTO_OPCODE(ip)                     @ jump to next instruction
5927    /* 12-15 instructions */
5928
5929
5930/* ------------------------------ */
5931    .balign 64
5932.L_OP_OR_LONG_2ADDR: /* 0xc1 */
5933/* File: armv5te/OP_OR_LONG_2ADDR.S */
5934/* File: armv5te/binopWide2addr.S */
5935    /*
5936     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5937     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5938     * This could be an ARM instruction or a function call.  (If the result
5939     * comes back in a register other than r0, you can override "result".)
5940     *
5941     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5942     * vCC (r1).  Useful for integer division and modulus.
5943     *
5944     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5945     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5946     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5947     *      rem-double/2addr
5948     */
5949    /* binop/2addr vA, vB */
5950    mov     r9, rINST, lsr #8           @ r9<- A+
5951    mov     r1, rINST, lsr #12          @ r1<- B
5952    and     r9, r9, #15
5953    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5954    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5955    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5956    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5957    .if 0
5958    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5959    beq     common_errDivideByZero
5960    .endif
5961    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5962
5963    orr     r0, r0, r2                           @ optional op; may set condition codes
5964    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
5965    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5966    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5967    GOTO_OPCODE(ip)                     @ jump to next instruction
5968    /* 12-15 instructions */
5969
5970
5971/* ------------------------------ */
5972    .balign 64
5973.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
5974/* File: armv5te/OP_XOR_LONG_2ADDR.S */
5975/* File: armv5te/binopWide2addr.S */
5976    /*
5977     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5978     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5979     * This could be an ARM instruction or a function call.  (If the result
5980     * comes back in a register other than r0, you can override "result".)
5981     *
5982     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5983     * vCC (r1).  Useful for integer division and modulus.
5984     *
5985     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5986     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5987     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5988     *      rem-double/2addr
5989     */
5990    /* binop/2addr vA, vB */
5991    mov     r9, rINST, lsr #8           @ r9<- A+
5992    mov     r1, rINST, lsr #12          @ r1<- B
5993    and     r9, r9, #15
5994    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5995    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5996    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5997    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5998    .if 0
5999    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6000    beq     common_errDivideByZero
6001    .endif
6002    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6003
6004    eor     r0, r0, r2                           @ optional op; may set condition codes
6005    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6006    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6007    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6008    GOTO_OPCODE(ip)                     @ jump to next instruction
6009    /* 12-15 instructions */
6010
6011
6012/* ------------------------------ */
6013    .balign 64
6014.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6015/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6016    /*
6017     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6018     * 32-bit shift distance.
6019     */
6020    /* shl-long/2addr vA, vB */
6021    mov     r9, rINST, lsr #8           @ r9<- A+
6022    mov     r3, rINST, lsr #12          @ r3<- B
6023    and     r9, r9, #15
6024    GET_VREG(r2, r3)                    @ r2<- vB
6025    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6026    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6027    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6028
6029    mov     r1, r1, asl r2              @  r1<- r1 << r2
6030    rsb     r3, r2, #32                 @  r3<- 32 - r2
6031    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6032    subs    ip, r2, #32                 @  ip<- r2 - 32
6033    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6034    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6035    mov     r0, r0, asl r2              @  r0<- r0 << r2
6036    b       .LOP_SHL_LONG_2ADDR_finish
6037
6038/* ------------------------------ */
6039    .balign 64
6040.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6041/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6042    /*
6043     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6044     * 32-bit shift distance.
6045     */
6046    /* shr-long/2addr vA, vB */
6047    mov     r9, rINST, lsr #8           @ r9<- A+
6048    mov     r3, rINST, lsr #12          @ r3<- B
6049    and     r9, r9, #15
6050    GET_VREG(r2, r3)                    @ r2<- vB
6051    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6052    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6053    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6054
6055    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6056    rsb     r3, r2, #32                 @  r3<- 32 - r2
6057    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6058    subs    ip, r2, #32                 @  ip<- r2 - 32
6059    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6060    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6061    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6062    b       .LOP_SHR_LONG_2ADDR_finish
6063
6064/* ------------------------------ */
6065    .balign 64
6066.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6067/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6068    /*
6069     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6070     * 32-bit shift distance.
6071     */
6072    /* ushr-long/2addr vA, vB */
6073    mov     r9, rINST, lsr #8           @ r9<- A+
6074    mov     r3, rINST, lsr #12          @ r3<- B
6075    and     r9, r9, #15
6076    GET_VREG(r2, r3)                    @ r2<- vB
6077    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6078    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6079    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6080
6081    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6082    rsb     r3, r2, #32                 @  r3<- 32 - r2
6083    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6084    subs    ip, r2, #32                 @  ip<- r2 - 32
6085    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6086    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6087    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6088    b       .LOP_USHR_LONG_2ADDR_finish
6089
6090/* ------------------------------ */
6091    .balign 64
6092.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6093/* File: arm-vfp/OP_ADD_FLOAT_2ADDR.S */
6094/* File: arm-vfp/fbinop2addr.S */
6095    /*
6096     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6097     * an "instr" line that specifies an instruction that performs
6098     * "s2 = s0 op s1".
6099     *
6100     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6101     */
6102    /* binop/2addr vA, vB */
6103    mov     r3, rINST, lsr #12          @ r3<- B
6104    mov     r9, rINST, lsr #8           @ r9<- A+
6105    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6106    and     r9, r9, #15                 @ r9<- A
6107    flds    s1, [r3]                    @ s1<- vB
6108    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6109    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6110    flds    s0, [r9]                    @ s0<- vA
6111
6112    fadds   s2, s0, s1                              @ s2<- op
6113    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6114    fsts    s2, [r9]                    @ vAA<- s2
6115    GOTO_OPCODE(ip)                     @ jump to next instruction
6116
6117
6118/* ------------------------------ */
6119    .balign 64
6120.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6121/* File: arm-vfp/OP_SUB_FLOAT_2ADDR.S */
6122/* File: arm-vfp/fbinop2addr.S */
6123    /*
6124     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6125     * an "instr" line that specifies an instruction that performs
6126     * "s2 = s0 op s1".
6127     *
6128     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6129     */
6130    /* binop/2addr vA, vB */
6131    mov     r3, rINST, lsr #12          @ r3<- B
6132    mov     r9, rINST, lsr #8           @ r9<- A+
6133    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6134    and     r9, r9, #15                 @ r9<- A
6135    flds    s1, [r3]                    @ s1<- vB
6136    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6137    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6138    flds    s0, [r9]                    @ s0<- vA
6139
6140    fsubs   s2, s0, s1                              @ s2<- op
6141    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6142    fsts    s2, [r9]                    @ vAA<- s2
6143    GOTO_OPCODE(ip)                     @ jump to next instruction
6144
6145
6146/* ------------------------------ */
6147    .balign 64
6148.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6149/* File: arm-vfp/OP_MUL_FLOAT_2ADDR.S */
6150/* File: arm-vfp/fbinop2addr.S */
6151    /*
6152     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6153     * an "instr" line that specifies an instruction that performs
6154     * "s2 = s0 op s1".
6155     *
6156     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6157     */
6158    /* binop/2addr vA, vB */
6159    mov     r3, rINST, lsr #12          @ r3<- B
6160    mov     r9, rINST, lsr #8           @ r9<- A+
6161    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6162    and     r9, r9, #15                 @ r9<- A
6163    flds    s1, [r3]                    @ s1<- vB
6164    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6165    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6166    flds    s0, [r9]                    @ s0<- vA
6167
6168    fmuls   s2, s0, s1                              @ s2<- op
6169    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6170    fsts    s2, [r9]                    @ vAA<- s2
6171    GOTO_OPCODE(ip)                     @ jump to next instruction
6172
6173
6174/* ------------------------------ */
6175    .balign 64
6176.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6177/* File: arm-vfp/OP_DIV_FLOAT_2ADDR.S */
6178/* File: arm-vfp/fbinop2addr.S */
6179    /*
6180     * Generic 32-bit floating point "/2addr" binary operation.  Provide
6181     * an "instr" line that specifies an instruction that performs
6182     * "s2 = s0 op s1".
6183     *
6184     * For: add-float/2addr, sub-float/2addr, mul-float/2addr, div-float/2addr
6185     */
6186    /* binop/2addr vA, vB */
6187    mov     r3, rINST, lsr #12          @ r3<- B
6188    mov     r9, rINST, lsr #8           @ r9<- A+
6189    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6190    and     r9, r9, #15                 @ r9<- A
6191    flds    s1, [r3]                    @ s1<- vB
6192    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6193    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6194    flds    s0, [r9]                    @ s0<- vA
6195
6196    fdivs   s2, s0, s1                              @ s2<- op
6197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6198    fsts    s2, [r9]                    @ vAA<- s2
6199    GOTO_OPCODE(ip)                     @ jump to next instruction
6200
6201
6202/* ------------------------------ */
6203    .balign 64
6204.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6205/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6206/* EABI doesn't define a float remainder function, but libm does */
6207/* File: armv5te/binop2addr.S */
6208    /*
6209     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6210     * that specifies an instruction that performs "result = r0 op r1".
6211     * This could be an ARM instruction or a function call.  (If the result
6212     * comes back in a register other than r0, you can override "result".)
6213     *
6214     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6215     * vCC (r1).  Useful for integer division and modulus.
6216     *
6217     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6218     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6219     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6220     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6221     */
6222    /* binop/2addr vA, vB */
6223    mov     r9, rINST, lsr #8           @ r9<- A+
6224    mov     r3, rINST, lsr #12          @ r3<- B
6225    and     r9, r9, #15
6226    GET_VREG(r1, r3)                    @ r1<- vB
6227    GET_VREG(r0, r9)                    @ r0<- vA
6228    .if 0
6229    cmp     r1, #0                      @ is second operand zero?
6230    beq     common_errDivideByZero
6231    .endif
6232    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6233
6234                               @ optional op; may set condition codes
6235    bl      fmodf                              @ r0<- op, r0-r3 changed
6236    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6237    SET_VREG(r0, r9)               @ vAA<- r0
6238    GOTO_OPCODE(ip)                     @ jump to next instruction
6239    /* 10-13 instructions */
6240
6241
6242/* ------------------------------ */
6243    .balign 64
6244.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6245/* File: arm-vfp/OP_ADD_DOUBLE_2ADDR.S */
6246/* File: arm-vfp/fbinopWide2addr.S */
6247    /*
6248     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6249     * an "instr" line that specifies an instruction that performs
6250     * "d2 = d0 op d1".
6251     *
6252     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6253     *      div-double/2addr
6254     */
6255    /* binop/2addr vA, vB */
6256    mov     r3, rINST, lsr #12          @ r3<- B
6257    mov     r9, rINST, lsr #8           @ r9<- A+
6258    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6259    and     r9, r9, #15                 @ r9<- A
6260    fldd    d1, [r3]                    @ d1<- vB
6261    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6262    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6263    fldd    d0, [r9]                    @ d0<- vA
6264
6265    faddd   d2, d0, d1                              @ d2<- op
6266    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6267    fstd    d2, [r9]                    @ vAA<- d2
6268    GOTO_OPCODE(ip)                     @ jump to next instruction
6269
6270
6271/* ------------------------------ */
6272    .balign 64
6273.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6274/* File: arm-vfp/OP_SUB_DOUBLE_2ADDR.S */
6275/* File: arm-vfp/fbinopWide2addr.S */
6276    /*
6277     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6278     * an "instr" line that specifies an instruction that performs
6279     * "d2 = d0 op d1".
6280     *
6281     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6282     *      div-double/2addr
6283     */
6284    /* binop/2addr vA, vB */
6285    mov     r3, rINST, lsr #12          @ r3<- B
6286    mov     r9, rINST, lsr #8           @ r9<- A+
6287    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6288    and     r9, r9, #15                 @ r9<- A
6289    fldd    d1, [r3]                    @ d1<- vB
6290    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6291    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6292    fldd    d0, [r9]                    @ d0<- vA
6293
6294    fsubd   d2, d0, d1                              @ d2<- op
6295    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6296    fstd    d2, [r9]                    @ vAA<- d2
6297    GOTO_OPCODE(ip)                     @ jump to next instruction
6298
6299
6300/* ------------------------------ */
6301    .balign 64
6302.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6303/* File: arm-vfp/OP_MUL_DOUBLE_2ADDR.S */
6304/* File: arm-vfp/fbinopWide2addr.S */
6305    /*
6306     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6307     * an "instr" line that specifies an instruction that performs
6308     * "d2 = d0 op d1".
6309     *
6310     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6311     *      div-double/2addr
6312     */
6313    /* binop/2addr vA, vB */
6314    mov     r3, rINST, lsr #12          @ r3<- B
6315    mov     r9, rINST, lsr #8           @ r9<- A+
6316    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6317    and     r9, r9, #15                 @ r9<- A
6318    fldd    d1, [r3]                    @ d1<- vB
6319    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6320    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6321    fldd    d0, [r9]                    @ d0<- vA
6322
6323    fmuld   d2, d0, d1                              @ d2<- op
6324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6325    fstd    d2, [r9]                    @ vAA<- d2
6326    GOTO_OPCODE(ip)                     @ jump to next instruction
6327
6328
6329/* ------------------------------ */
6330    .balign 64
6331.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6332/* File: arm-vfp/OP_DIV_DOUBLE_2ADDR.S */
6333/* File: arm-vfp/fbinopWide2addr.S */
6334    /*
6335     * Generic 64-bit floating point "/2addr" binary operation.  Provide
6336     * an "instr" line that specifies an instruction that performs
6337     * "d2 = d0 op d1".
6338     *
6339     * For: add-double/2addr, sub-double/2addr, mul-double/2addr,
6340     *      div-double/2addr
6341     */
6342    /* binop/2addr vA, vB */
6343    mov     r3, rINST, lsr #12          @ r3<- B
6344    mov     r9, rINST, lsr #8           @ r9<- A+
6345    VREG_INDEX_TO_ADDR(r3, r3)          @ r3<- &vB
6346    and     r9, r9, #15                 @ r9<- A
6347    fldd    d1, [r3]                    @ d1<- vB
6348    VREG_INDEX_TO_ADDR(r9, r9)          @ r9<- &vA
6349    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6350    fldd    d0, [r9]                    @ d0<- vA
6351
6352    fdivd   d2, d0, d1                              @ d2<- op
6353    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6354    fstd    d2, [r9]                    @ vAA<- d2
6355    GOTO_OPCODE(ip)                     @ jump to next instruction
6356
6357
6358/* ------------------------------ */
6359    .balign 64
6360.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6361/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6362/* EABI doesn't define a double remainder function, but libm does */
6363/* File: armv5te/binopWide2addr.S */
6364    /*
6365     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6366     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6367     * This could be an ARM instruction or a function call.  (If the result
6368     * comes back in a register other than r0, you can override "result".)
6369     *
6370     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6371     * vCC (r1).  Useful for integer division and modulus.
6372     *
6373     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6374     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6375     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6376     *      rem-double/2addr
6377     */
6378    /* binop/2addr vA, vB */
6379    mov     r9, rINST, lsr #8           @ r9<- A+
6380    mov     r1, rINST, lsr #12          @ r1<- B
6381    and     r9, r9, #15
6382    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6383    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6384    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6385    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6386    .if 0
6387    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6388    beq     common_errDivideByZero
6389    .endif
6390    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6391
6392                               @ optional op; may set condition codes
6393    bl      fmod                              @ result<- op, r0-r3 changed
6394    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6395    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6396    GOTO_OPCODE(ip)                     @ jump to next instruction
6397    /* 12-15 instructions */
6398
6399
6400/* ------------------------------ */
6401    .balign 64
6402.L_OP_ADD_INT_LIT16: /* 0xd0 */
6403/* File: armv5te/OP_ADD_INT_LIT16.S */
6404/* File: armv5te/binopLit16.S */
6405    /*
6406     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6407     * that specifies an instruction that performs "result = r0 op r1".
6408     * This could be an ARM instruction or a function call.  (If the result
6409     * comes back in a register other than r0, you can override "result".)
6410     *
6411     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6412     * vCC (r1).  Useful for integer division and modulus.
6413     *
6414     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6415     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6416     */
6417    /* binop/lit16 vA, vB, #+CCCC */
6418    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6419    mov     r2, rINST, lsr #12          @ r2<- B
6420    mov     r9, rINST, lsr #8           @ r9<- A+
6421    GET_VREG(r0, r2)                    @ r0<- vB
6422    and     r9, r9, #15
6423    .if 0
6424    cmp     r1, #0                      @ is second operand zero?
6425    beq     common_errDivideByZero
6426    .endif
6427    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6428
6429    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6430    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6431    SET_VREG(r0, r9)               @ vAA<- r0
6432    GOTO_OPCODE(ip)                     @ jump to next instruction
6433    /* 10-13 instructions */
6434
6435
6436/* ------------------------------ */
6437    .balign 64
6438.L_OP_RSUB_INT: /* 0xd1 */
6439/* File: armv5te/OP_RSUB_INT.S */
6440/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6441/* File: armv5te/binopLit16.S */
6442    /*
6443     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6444     * that specifies an instruction that performs "result = r0 op r1".
6445     * This could be an ARM instruction or a function call.  (If the result
6446     * comes back in a register other than r0, you can override "result".)
6447     *
6448     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6449     * vCC (r1).  Useful for integer division and modulus.
6450     *
6451     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6452     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6453     */
6454    /* binop/lit16 vA, vB, #+CCCC */
6455    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6456    mov     r2, rINST, lsr #12          @ r2<- B
6457    mov     r9, rINST, lsr #8           @ r9<- A+
6458    GET_VREG(r0, r2)                    @ r0<- vB
6459    and     r9, r9, #15
6460    .if 0
6461    cmp     r1, #0                      @ is second operand zero?
6462    beq     common_errDivideByZero
6463    .endif
6464    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6465
6466    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6467    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6468    SET_VREG(r0, r9)               @ vAA<- r0
6469    GOTO_OPCODE(ip)                     @ jump to next instruction
6470    /* 10-13 instructions */
6471
6472
6473/* ------------------------------ */
6474    .balign 64
6475.L_OP_MUL_INT_LIT16: /* 0xd2 */
6476/* File: armv5te/OP_MUL_INT_LIT16.S */
6477/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6478/* File: armv5te/binopLit16.S */
6479    /*
6480     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6481     * that specifies an instruction that performs "result = r0 op r1".
6482     * This could be an ARM instruction or a function call.  (If the result
6483     * comes back in a register other than r0, you can override "result".)
6484     *
6485     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6486     * vCC (r1).  Useful for integer division and modulus.
6487     *
6488     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6489     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6490     */
6491    /* binop/lit16 vA, vB, #+CCCC */
6492    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6493    mov     r2, rINST, lsr #12          @ r2<- B
6494    mov     r9, rINST, lsr #8           @ r9<- A+
6495    GET_VREG(r0, r2)                    @ r0<- vB
6496    and     r9, r9, #15
6497    .if 0
6498    cmp     r1, #0                      @ is second operand zero?
6499    beq     common_errDivideByZero
6500    .endif
6501    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6502
6503    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6504    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6505    SET_VREG(r0, r9)               @ vAA<- r0
6506    GOTO_OPCODE(ip)                     @ jump to next instruction
6507    /* 10-13 instructions */
6508
6509
6510/* ------------------------------ */
6511    .balign 64
6512.L_OP_DIV_INT_LIT16: /* 0xd3 */
6513/* File: armv5te/OP_DIV_INT_LIT16.S */
6514/* File: armv5te/binopLit16.S */
6515    /*
6516     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6517     * that specifies an instruction that performs "result = r0 op r1".
6518     * This could be an ARM instruction or a function call.  (If the result
6519     * comes back in a register other than r0, you can override "result".)
6520     *
6521     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6522     * vCC (r1).  Useful for integer division and modulus.
6523     *
6524     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6525     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6526     */
6527    /* binop/lit16 vA, vB, #+CCCC */
6528    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6529    mov     r2, rINST, lsr #12          @ r2<- B
6530    mov     r9, rINST, lsr #8           @ r9<- A+
6531    GET_VREG(r0, r2)                    @ r0<- vB
6532    and     r9, r9, #15
6533    .if 1
6534    cmp     r1, #0                      @ is second operand zero?
6535    beq     common_errDivideByZero
6536    .endif
6537    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6538
6539    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6540    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6541    SET_VREG(r0, r9)               @ vAA<- r0
6542    GOTO_OPCODE(ip)                     @ jump to next instruction
6543    /* 10-13 instructions */
6544
6545
6546/* ------------------------------ */
6547    .balign 64
6548.L_OP_REM_INT_LIT16: /* 0xd4 */
6549/* File: armv5te/OP_REM_INT_LIT16.S */
6550/* idivmod returns quotient in r0 and remainder in r1 */
6551/* File: armv5te/binopLit16.S */
6552    /*
6553     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6554     * that specifies an instruction that performs "result = r0 op r1".
6555     * This could be an ARM instruction or a function call.  (If the result
6556     * comes back in a register other than r0, you can override "result".)
6557     *
6558     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6559     * vCC (r1).  Useful for integer division and modulus.
6560     *
6561     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6562     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6563     */
6564    /* binop/lit16 vA, vB, #+CCCC */
6565    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6566    mov     r2, rINST, lsr #12          @ r2<- B
6567    mov     r9, rINST, lsr #8           @ r9<- A+
6568    GET_VREG(r0, r2)                    @ r0<- vB
6569    and     r9, r9, #15
6570    .if 1
6571    cmp     r1, #0                      @ is second operand zero?
6572    beq     common_errDivideByZero
6573    .endif
6574    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6575
6576    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6577    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6578    SET_VREG(r1, r9)               @ vAA<- r1
6579    GOTO_OPCODE(ip)                     @ jump to next instruction
6580    /* 10-13 instructions */
6581
6582
6583/* ------------------------------ */
6584    .balign 64
6585.L_OP_AND_INT_LIT16: /* 0xd5 */
6586/* File: armv5te/OP_AND_INT_LIT16.S */
6587/* File: armv5te/binopLit16.S */
6588    /*
6589     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6590     * that specifies an instruction that performs "result = r0 op r1".
6591     * This could be an ARM instruction or a function call.  (If the result
6592     * comes back in a register other than r0, you can override "result".)
6593     *
6594     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6595     * vCC (r1).  Useful for integer division and modulus.
6596     *
6597     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6598     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6599     */
6600    /* binop/lit16 vA, vB, #+CCCC */
6601    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6602    mov     r2, rINST, lsr #12          @ r2<- B
6603    mov     r9, rINST, lsr #8           @ r9<- A+
6604    GET_VREG(r0, r2)                    @ r0<- vB
6605    and     r9, r9, #15
6606    .if 0
6607    cmp     r1, #0                      @ is second operand zero?
6608    beq     common_errDivideByZero
6609    .endif
6610    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6611
6612    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6613    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6614    SET_VREG(r0, r9)               @ vAA<- r0
6615    GOTO_OPCODE(ip)                     @ jump to next instruction
6616    /* 10-13 instructions */
6617
6618
6619/* ------------------------------ */
6620    .balign 64
6621.L_OP_OR_INT_LIT16: /* 0xd6 */
6622/* File: armv5te/OP_OR_INT_LIT16.S */
6623/* File: armv5te/binopLit16.S */
6624    /*
6625     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6626     * that specifies an instruction that performs "result = r0 op r1".
6627     * This could be an ARM instruction or a function call.  (If the result
6628     * comes back in a register other than r0, you can override "result".)
6629     *
6630     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6631     * vCC (r1).  Useful for integer division and modulus.
6632     *
6633     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6634     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6635     */
6636    /* binop/lit16 vA, vB, #+CCCC */
6637    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6638    mov     r2, rINST, lsr #12          @ r2<- B
6639    mov     r9, rINST, lsr #8           @ r9<- A+
6640    GET_VREG(r0, r2)                    @ r0<- vB
6641    and     r9, r9, #15
6642    .if 0
6643    cmp     r1, #0                      @ is second operand zero?
6644    beq     common_errDivideByZero
6645    .endif
6646    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6647
6648    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6649    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6650    SET_VREG(r0, r9)               @ vAA<- r0
6651    GOTO_OPCODE(ip)                     @ jump to next instruction
6652    /* 10-13 instructions */
6653
6654
6655/* ------------------------------ */
6656    .balign 64
6657.L_OP_XOR_INT_LIT16: /* 0xd7 */
6658/* File: armv5te/OP_XOR_INT_LIT16.S */
6659/* File: armv5te/binopLit16.S */
6660    /*
6661     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6662     * that specifies an instruction that performs "result = r0 op r1".
6663     * This could be an ARM instruction or a function call.  (If the result
6664     * comes back in a register other than r0, you can override "result".)
6665     *
6666     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6667     * vCC (r1).  Useful for integer division and modulus.
6668     *
6669     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6670     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6671     */
6672    /* binop/lit16 vA, vB, #+CCCC */
6673    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6674    mov     r2, rINST, lsr #12          @ r2<- B
6675    mov     r9, rINST, lsr #8           @ r9<- A+
6676    GET_VREG(r0, r2)                    @ r0<- vB
6677    and     r9, r9, #15
6678    .if 0
6679    cmp     r1, #0                      @ is second operand zero?
6680    beq     common_errDivideByZero
6681    .endif
6682    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6683
6684    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6685    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6686    SET_VREG(r0, r9)               @ vAA<- r0
6687    GOTO_OPCODE(ip)                     @ jump to next instruction
6688    /* 10-13 instructions */
6689
6690
6691/* ------------------------------ */
6692    .balign 64
6693.L_OP_ADD_INT_LIT8: /* 0xd8 */
6694/* File: armv5te/OP_ADD_INT_LIT8.S */
6695/* File: armv5te/binopLit8.S */
6696    /*
6697     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6698     * that specifies an instruction that performs "result = r0 op r1".
6699     * This could be an ARM instruction or a function call.  (If the result
6700     * comes back in a register other than r0, you can override "result".)
6701     *
6702     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6703     * vCC (r1).  Useful for integer division and modulus.
6704     *
6705     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6706     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6707     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6708     */
6709    /* binop/lit8 vAA, vBB, #+CC */
6710    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6711    mov     r9, rINST, lsr #8           @ r9<- AA
6712    and     r2, r3, #255                @ r2<- BB
6713    GET_VREG(r0, r2)                    @ r0<- vBB
6714    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6715    .if 0
6716    @cmp     r1, #0                      @ is second operand zero?
6717    beq     common_errDivideByZero
6718    .endif
6719    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6720
6721                               @ optional op; may set condition codes
6722    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6723    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6724    SET_VREG(r0, r9)               @ vAA<- r0
6725    GOTO_OPCODE(ip)                     @ jump to next instruction
6726    /* 10-12 instructions */
6727
6728
6729/* ------------------------------ */
6730    .balign 64
6731.L_OP_RSUB_INT_LIT8: /* 0xd9 */
6732/* File: armv5te/OP_RSUB_INT_LIT8.S */
6733/* File: armv5te/binopLit8.S */
6734    /*
6735     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6736     * that specifies an instruction that performs "result = r0 op r1".
6737     * This could be an ARM instruction or a function call.  (If the result
6738     * comes back in a register other than r0, you can override "result".)
6739     *
6740     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6741     * vCC (r1).  Useful for integer division and modulus.
6742     *
6743     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6744     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6745     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6746     */
6747    /* binop/lit8 vAA, vBB, #+CC */
6748    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6749    mov     r9, rINST, lsr #8           @ r9<- AA
6750    and     r2, r3, #255                @ r2<- BB
6751    GET_VREG(r0, r2)                    @ r0<- vBB
6752    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6753    .if 0
6754    @cmp     r1, #0                      @ is second operand zero?
6755    beq     common_errDivideByZero
6756    .endif
6757    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6758
6759                               @ optional op; may set condition codes
6760    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6761    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6762    SET_VREG(r0, r9)               @ vAA<- r0
6763    GOTO_OPCODE(ip)                     @ jump to next instruction
6764    /* 10-12 instructions */
6765
6766
6767/* ------------------------------ */
6768    .balign 64
6769.L_OP_MUL_INT_LIT8: /* 0xda */
6770/* File: armv5te/OP_MUL_INT_LIT8.S */
6771/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6772/* File: armv5te/binopLit8.S */
6773    /*
6774     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6775     * that specifies an instruction that performs "result = r0 op r1".
6776     * This could be an ARM instruction or a function call.  (If the result
6777     * comes back in a register other than r0, you can override "result".)
6778     *
6779     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6780     * vCC (r1).  Useful for integer division and modulus.
6781     *
6782     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6783     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6784     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6785     */
6786    /* binop/lit8 vAA, vBB, #+CC */
6787    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6788    mov     r9, rINST, lsr #8           @ r9<- AA
6789    and     r2, r3, #255                @ r2<- BB
6790    GET_VREG(r0, r2)                    @ r0<- vBB
6791    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6792    .if 0
6793    @cmp     r1, #0                      @ is second operand zero?
6794    beq     common_errDivideByZero
6795    .endif
6796    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6797
6798                               @ optional op; may set condition codes
6799    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6801    SET_VREG(r0, r9)               @ vAA<- r0
6802    GOTO_OPCODE(ip)                     @ jump to next instruction
6803    /* 10-12 instructions */
6804
6805
6806/* ------------------------------ */
6807    .balign 64
6808.L_OP_DIV_INT_LIT8: /* 0xdb */
6809/* File: armv5te/OP_DIV_INT_LIT8.S */
6810/* File: armv5te/binopLit8.S */
6811    /*
6812     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6813     * that specifies an instruction that performs "result = r0 op r1".
6814     * This could be an ARM instruction or a function call.  (If the result
6815     * comes back in a register other than r0, you can override "result".)
6816     *
6817     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6818     * vCC (r1).  Useful for integer division and modulus.
6819     *
6820     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6821     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6822     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6823     */
6824    /* binop/lit8 vAA, vBB, #+CC */
6825    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6826    mov     r9, rINST, lsr #8           @ r9<- AA
6827    and     r2, r3, #255                @ r2<- BB
6828    GET_VREG(r0, r2)                    @ r0<- vBB
6829    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6830    .if 1
6831    @cmp     r1, #0                      @ is second operand zero?
6832    beq     common_errDivideByZero
6833    .endif
6834    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6835
6836                               @ optional op; may set condition codes
6837    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6838    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6839    SET_VREG(r0, r9)               @ vAA<- r0
6840    GOTO_OPCODE(ip)                     @ jump to next instruction
6841    /* 10-12 instructions */
6842
6843
6844/* ------------------------------ */
6845    .balign 64
6846.L_OP_REM_INT_LIT8: /* 0xdc */
6847/* File: armv5te/OP_REM_INT_LIT8.S */
6848/* idivmod returns quotient in r0 and remainder in r1 */
6849/* File: armv5te/binopLit8.S */
6850    /*
6851     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6852     * that specifies an instruction that performs "result = r0 op r1".
6853     * This could be an ARM instruction or a function call.  (If the result
6854     * comes back in a register other than r0, you can override "result".)
6855     *
6856     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6857     * vCC (r1).  Useful for integer division and modulus.
6858     *
6859     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6860     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6861     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6862     */
6863    /* binop/lit8 vAA, vBB, #+CC */
6864    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6865    mov     r9, rINST, lsr #8           @ r9<- AA
6866    and     r2, r3, #255                @ r2<- BB
6867    GET_VREG(r0, r2)                    @ r0<- vBB
6868    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6869    .if 1
6870    @cmp     r1, #0                      @ is second operand zero?
6871    beq     common_errDivideByZero
6872    .endif
6873    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6874
6875                               @ optional op; may set condition codes
6876    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6878    SET_VREG(r1, r9)               @ vAA<- r1
6879    GOTO_OPCODE(ip)                     @ jump to next instruction
6880    /* 10-12 instructions */
6881
6882
6883/* ------------------------------ */
6884    .balign 64
6885.L_OP_AND_INT_LIT8: /* 0xdd */
6886/* File: armv5te/OP_AND_INT_LIT8.S */
6887/* File: armv5te/binopLit8.S */
6888    /*
6889     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6890     * that specifies an instruction that performs "result = r0 op r1".
6891     * This could be an ARM instruction or a function call.  (If the result
6892     * comes back in a register other than r0, you can override "result".)
6893     *
6894     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6895     * vCC (r1).  Useful for integer division and modulus.
6896     *
6897     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6898     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6899     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6900     */
6901    /* binop/lit8 vAA, vBB, #+CC */
6902    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6903    mov     r9, rINST, lsr #8           @ r9<- AA
6904    and     r2, r3, #255                @ r2<- BB
6905    GET_VREG(r0, r2)                    @ r0<- vBB
6906    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6907    .if 0
6908    @cmp     r1, #0                      @ is second operand zero?
6909    beq     common_errDivideByZero
6910    .endif
6911    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6912
6913                               @ optional op; may set condition codes
6914    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6916    SET_VREG(r0, r9)               @ vAA<- r0
6917    GOTO_OPCODE(ip)                     @ jump to next instruction
6918    /* 10-12 instructions */
6919
6920
6921/* ------------------------------ */
6922    .balign 64
6923.L_OP_OR_INT_LIT8: /* 0xde */
6924/* File: armv5te/OP_OR_INT_LIT8.S */
6925/* File: armv5te/binopLit8.S */
6926    /*
6927     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6928     * that specifies an instruction that performs "result = r0 op r1".
6929     * This could be an ARM instruction or a function call.  (If the result
6930     * comes back in a register other than r0, you can override "result".)
6931     *
6932     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6933     * vCC (r1).  Useful for integer division and modulus.
6934     *
6935     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6936     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6937     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6938     */
6939    /* binop/lit8 vAA, vBB, #+CC */
6940    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6941    mov     r9, rINST, lsr #8           @ r9<- AA
6942    and     r2, r3, #255                @ r2<- BB
6943    GET_VREG(r0, r2)                    @ r0<- vBB
6944    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6945    .if 0
6946    @cmp     r1, #0                      @ is second operand zero?
6947    beq     common_errDivideByZero
6948    .endif
6949    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6950
6951                               @ optional op; may set condition codes
6952    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6953    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6954    SET_VREG(r0, r9)               @ vAA<- r0
6955    GOTO_OPCODE(ip)                     @ jump to next instruction
6956    /* 10-12 instructions */
6957
6958
6959/* ------------------------------ */
6960    .balign 64
6961.L_OP_XOR_INT_LIT8: /* 0xdf */
6962/* File: armv5te/OP_XOR_INT_LIT8.S */
6963/* File: armv5te/binopLit8.S */
6964    /*
6965     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
6966     * that specifies an instruction that performs "result = r0 op r1".
6967     * This could be an ARM instruction or a function call.  (If the result
6968     * comes back in a register other than r0, you can override "result".)
6969     *
6970     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6971     * vCC (r1).  Useful for integer division and modulus.
6972     *
6973     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
6974     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
6975     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
6976     */
6977    /* binop/lit8 vAA, vBB, #+CC */
6978    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
6979    mov     r9, rINST, lsr #8           @ r9<- AA
6980    and     r2, r3, #255                @ r2<- BB
6981    GET_VREG(r0, r2)                    @ r0<- vBB
6982    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
6983    .if 0
6984    @cmp     r1, #0                      @ is second operand zero?
6985    beq     common_errDivideByZero
6986    .endif
6987    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6988
6989                               @ optional op; may set condition codes
6990    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
6991    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6992    SET_VREG(r0, r9)               @ vAA<- r0
6993    GOTO_OPCODE(ip)                     @ jump to next instruction
6994    /* 10-12 instructions */
6995
6996
6997/* ------------------------------ */
6998    .balign 64
6999.L_OP_SHL_INT_LIT8: /* 0xe0 */
7000/* File: armv5te/OP_SHL_INT_LIT8.S */
7001/* File: armv5te/binopLit8.S */
7002    /*
7003     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7004     * that specifies an instruction that performs "result = r0 op r1".
7005     * This could be an ARM instruction or a function call.  (If the result
7006     * comes back in a register other than r0, you can override "result".)
7007     *
7008     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7009     * vCC (r1).  Useful for integer division and modulus.
7010     *
7011     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7012     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7013     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7014     */
7015    /* binop/lit8 vAA, vBB, #+CC */
7016    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7017    mov     r9, rINST, lsr #8           @ r9<- AA
7018    and     r2, r3, #255                @ r2<- BB
7019    GET_VREG(r0, r2)                    @ r0<- vBB
7020    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7021    .if 0
7022    @cmp     r1, #0                      @ is second operand zero?
7023    beq     common_errDivideByZero
7024    .endif
7025    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7026
7027    and     r1, r1, #31                           @ optional op; may set condition codes
7028    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7030    SET_VREG(r0, r9)               @ vAA<- r0
7031    GOTO_OPCODE(ip)                     @ jump to next instruction
7032    /* 10-12 instructions */
7033
7034
7035/* ------------------------------ */
7036    .balign 64
7037.L_OP_SHR_INT_LIT8: /* 0xe1 */
7038/* File: armv5te/OP_SHR_INT_LIT8.S */
7039/* File: armv5te/binopLit8.S */
7040    /*
7041     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7042     * that specifies an instruction that performs "result = r0 op r1".
7043     * This could be an ARM instruction or a function call.  (If the result
7044     * comes back in a register other than r0, you can override "result".)
7045     *
7046     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7047     * vCC (r1).  Useful for integer division and modulus.
7048     *
7049     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7050     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7051     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7052     */
7053    /* binop/lit8 vAA, vBB, #+CC */
7054    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7055    mov     r9, rINST, lsr #8           @ r9<- AA
7056    and     r2, r3, #255                @ r2<- BB
7057    GET_VREG(r0, r2)                    @ r0<- vBB
7058    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7059    .if 0
7060    @cmp     r1, #0                      @ is second operand zero?
7061    beq     common_errDivideByZero
7062    .endif
7063    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7064
7065    and     r1, r1, #31                           @ optional op; may set condition codes
7066    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7067    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7068    SET_VREG(r0, r9)               @ vAA<- r0
7069    GOTO_OPCODE(ip)                     @ jump to next instruction
7070    /* 10-12 instructions */
7071
7072
7073/* ------------------------------ */
7074    .balign 64
7075.L_OP_USHR_INT_LIT8: /* 0xe2 */
7076/* File: armv5te/OP_USHR_INT_LIT8.S */
7077/* File: armv5te/binopLit8.S */
7078    /*
7079     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7080     * that specifies an instruction that performs "result = r0 op r1".
7081     * This could be an ARM instruction or a function call.  (If the result
7082     * comes back in a register other than r0, you can override "result".)
7083     *
7084     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7085     * vCC (r1).  Useful for integer division and modulus.
7086     *
7087     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7088     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7089     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7090     */
7091    /* binop/lit8 vAA, vBB, #+CC */
7092    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7093    mov     r9, rINST, lsr #8           @ r9<- AA
7094    and     r2, r3, #255                @ r2<- BB
7095    GET_VREG(r0, r2)                    @ r0<- vBB
7096    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7097    .if 0
7098    @cmp     r1, #0                      @ is second operand zero?
7099    beq     common_errDivideByZero
7100    .endif
7101    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7102
7103    and     r1, r1, #31                           @ optional op; may set condition codes
7104    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7106    SET_VREG(r0, r9)               @ vAA<- r0
7107    GOTO_OPCODE(ip)                     @ jump to next instruction
7108    /* 10-12 instructions */
7109
7110
7111/* ------------------------------ */
7112    .balign 64
7113.L_OP_IGET_VOLATILE: /* 0xe3 */
7114/* File: armv5te/OP_IGET_VOLATILE.S */
7115/* File: armv5te/OP_IGET.S */
7116    /*
7117     * General 32-bit instance field get.
7118     *
7119     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7120     */
7121    /* op vA, vB, field@CCCC */
7122    mov     r0, rINST, lsr #12          @ r0<- B
7123    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7124    FETCH(r1, 1)                        @ r1<- field ref CCCC
7125    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7126    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7127    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7128    cmp     r0, #0                      @ is resolved entry null?
7129    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
71308:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7131    EXPORT_PC()                         @ resolve() could throw
7132    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7133    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7134    cmp     r0, #0
7135    bne     .LOP_IGET_VOLATILE_finish
7136    b       common_exceptionThrown
7137
7138
7139/* ------------------------------ */
7140    .balign 64
7141.L_OP_IPUT_VOLATILE: /* 0xe4 */
7142/* File: armv5te/OP_IPUT_VOLATILE.S */
7143/* File: armv5te/OP_IPUT.S */
7144    /*
7145     * General 32-bit instance field put.
7146     *
7147     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7148     */
7149    /* op vA, vB, field@CCCC */
7150    mov     r0, rINST, lsr #12          @ r0<- B
7151    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7152    FETCH(r1, 1)                        @ r1<- field ref CCCC
7153    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7154    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7155    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7156    cmp     r0, #0                      @ is resolved entry null?
7157    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
71588:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7159    EXPORT_PC()                         @ resolve() could throw
7160    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7161    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7162    cmp     r0, #0                      @ success?
7163    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7164    b       common_exceptionThrown
7165
7166
7167/* ------------------------------ */
7168    .balign 64
7169.L_OP_SGET_VOLATILE: /* 0xe5 */
7170/* File: armv5te/OP_SGET_VOLATILE.S */
7171/* File: armv5te/OP_SGET.S */
7172    /*
7173     * General 32-bit SGET handler.
7174     *
7175     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7176     */
7177    /* op vAA, field@BBBB */
7178    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7179    FETCH(r1, 1)                        @ r1<- field ref BBBB
7180    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7181    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7182    cmp     r0, #0                      @ is resolved entry null?
7183    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7184.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7185    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7186    SMP_DMB                            @ acquiring load
7187    mov     r2, rINST, lsr #8           @ r2<- AA
7188    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7189    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7190    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7191    GOTO_OPCODE(ip)                     @ jump to next instruction
7192
7193
7194/* ------------------------------ */
7195    .balign 64
7196.L_OP_SPUT_VOLATILE: /* 0xe6 */
7197/* File: armv5te/OP_SPUT_VOLATILE.S */
7198/* File: armv5te/OP_SPUT.S */
7199    /*
7200     * General 32-bit SPUT handler.
7201     *
7202     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7203     */
7204    /* op vAA, field@BBBB */
7205    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7206    FETCH(r1, 1)                        @ r1<- field ref BBBB
7207    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7208    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7209    cmp     r0, #0                      @ is resolved entry null?
7210    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7211.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7212    mov     r2, rINST, lsr #8           @ r2<- AA
7213    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7214    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7215    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7216    SMP_DMB                            @ releasing store
7217    str     r1, [r0, #offStaticField_value] @ field<- vAA
7218    GOTO_OPCODE(ip)                     @ jump to next instruction
7219
7220
7221/* ------------------------------ */
7222    .balign 64
7223.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7224/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7225/* File: armv5te/OP_IGET.S */
7226    /*
7227     * General 32-bit instance field get.
7228     *
7229     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7230     */
7231    /* op vA, vB, field@CCCC */
7232    mov     r0, rINST, lsr #12          @ r0<- B
7233    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7234    FETCH(r1, 1)                        @ r1<- field ref CCCC
7235    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7236    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7237    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7238    cmp     r0, #0                      @ is resolved entry null?
7239    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
72408:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7241    EXPORT_PC()                         @ resolve() could throw
7242    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7243    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7244    cmp     r0, #0
7245    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7246    b       common_exceptionThrown
7247
7248
7249/* ------------------------------ */
7250    .balign 64
7251.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7252/* File: armv5te/OP_IGET_WIDE_VOLATILE.S */
7253/* File: armv5te/OP_IGET_WIDE.S */
7254    /*
7255     * Wide 32-bit instance field get.
7256     */
7257    /* iget-wide vA, vB, field@CCCC */
7258    mov     r0, rINST, lsr #12          @ r0<- B
7259    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7260    FETCH(r1, 1)                        @ r1<- field ref CCCC
7261    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7262    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7263    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7264    cmp     r0, #0                      @ is resolved entry null?
7265    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
72668:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7267    EXPORT_PC()                         @ resolve() could throw
7268    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7269    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7270    cmp     r0, #0
7271    bne     .LOP_IGET_WIDE_VOLATILE_finish
7272    b       common_exceptionThrown
7273
7274
7275/* ------------------------------ */
7276    .balign 64
7277.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7278/* File: armv5te/OP_IPUT_WIDE_VOLATILE.S */
7279/* File: armv5te/OP_IPUT_WIDE.S */
7280    /* iput-wide vA, vB, field@CCCC */
7281    mov     r0, rINST, lsr #12          @ r0<- B
7282    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7283    FETCH(r1, 1)                        @ r1<- field ref CCCC
7284    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7285    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7286    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7287    cmp     r0, #0                      @ is resolved entry null?
7288    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
72898:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7290    EXPORT_PC()                         @ resolve() could throw
7291    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7292    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7293    cmp     r0, #0                      @ success?
7294    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7295    b       common_exceptionThrown
7296
7297
7298/* ------------------------------ */
7299    .balign 64
7300.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7301/* File: armv5te/OP_SGET_WIDE_VOLATILE.S */
7302/* File: armv5te/OP_SGET_WIDE.S */
7303    /*
7304     * 64-bit SGET handler.
7305     */
7306    /* sget-wide vAA, field@BBBB */
7307    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7308    FETCH(r1, 1)                        @ r1<- field ref BBBB
7309    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7310    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7311    cmp     r0, #0                      @ is resolved entry null?
7312    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7313.LOP_SGET_WIDE_VOLATILE_finish:
7314    mov     r9, rINST, lsr #8           @ r9<- AA
7315    .if 1
7316    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7317    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7318    .else
7319    ldrd    r0, [r0, #offStaticField_value] @ r0/r1<- field value (aligned)
7320    .endif
7321    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7322    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7323    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7324    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7325    GOTO_OPCODE(ip)                     @ jump to next instruction
7326
7327
7328/* ------------------------------ */
7329    .balign 64
7330.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7331/* File: armv5te/OP_SPUT_WIDE_VOLATILE.S */
7332/* File: armv5te/OP_SPUT_WIDE.S */
7333    /*
7334     * 64-bit SPUT handler.
7335     */
7336    /* sput-wide vAA, field@BBBB */
7337    ldr     r0, [rGLUE, #offGlue_methodClassDex]  @ r0<- DvmDex
7338    FETCH(r1, 1)                        @ r1<- field ref BBBB
7339    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7340    mov     r9, rINST, lsr #8           @ r9<- AA
7341    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7342    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7343    cmp     r2, #0                      @ is resolved entry null?
7344    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7345.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7346    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7347    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7348    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7349    .if 1
7350    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7351    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7352    .else
7353    strd    r0, [r2, #offStaticField_value] @ field<- vAA/vAA+1
7354    .endif
7355    GOTO_OPCODE(r10)                    @ jump to next instruction
7356
7357
7358/* ------------------------------ */
7359    .balign 64
7360.L_OP_BREAKPOINT: /* 0xec */
7361/* File: armv5te/OP_BREAKPOINT.S */
7362/* File: armv5te/unused.S */
7363    bl      common_abort
7364
7365
7366/* ------------------------------ */
7367    .balign 64
7368.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7369/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7370    /*
7371     * Handle a throw-verification-error instruction.  This throws an
7372     * exception for an error discovered during verification.  The
7373     * exception is indicated by AA, with some detail provided by BBBB.
7374     */
7375    /* op AA, ref@BBBB */
7376    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7377    FETCH(r2, 1)                        @ r2<- BBBB
7378    EXPORT_PC()                         @ export the PC
7379    mov     r1, rINST, lsr #8           @ r1<- AA
7380    bl      dvmThrowVerificationError   @ always throws
7381    b       common_exceptionThrown      @ handle exception
7382
7383/* ------------------------------ */
7384    .balign 64
7385.L_OP_EXECUTE_INLINE: /* 0xee */
7386/* File: armv5te/OP_EXECUTE_INLINE.S */
7387    /*
7388     * Execute a "native inline" instruction.
7389     *
7390     * We need to call an InlineOp4Func:
7391     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7392     *
7393     * The first four args are in r0-r3, pointer to return value storage
7394     * is on the stack.  The function's return value is a flag that tells
7395     * us if an exception was thrown.
7396     */
7397    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7398    FETCH(r10, 1)                       @ r10<- BBBB
7399    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7400    EXPORT_PC()                         @ can throw
7401    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7402    mov     r0, rINST, lsr #12          @ r0<- B
7403    str     r1, [sp]                    @ push &glue->retval
7404    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7405    add     sp, sp, #8                  @ pop stack
7406    cmp     r0, #0                      @ test boolean result of inline
7407    beq     common_exceptionThrown      @ returned false, handle exception
7408    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7409    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7410    GOTO_OPCODE(ip)                     @ jump to next instruction
7411
7412/* ------------------------------ */
7413    .balign 64
7414.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7415/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7416    /*
7417     * Execute a "native inline" instruction, using "/range" semantics.
7418     * Same idea as execute-inline, but we get the args differently.
7419     *
7420     * We need to call an InlineOp4Func:
7421     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7422     *
7423     * The first four args are in r0-r3, pointer to return value storage
7424     * is on the stack.  The function's return value is a flag that tells
7425     * us if an exception was thrown.
7426     */
7427    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7428    FETCH(r10, 1)                       @ r10<- BBBB
7429    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7430    EXPORT_PC()                         @ can throw
7431    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7432    mov     r0, rINST, lsr #8           @ r0<- AA
7433    str     r1, [sp]                    @ push &glue->retval
7434    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7435    add     sp, sp, #8                  @ pop stack
7436    cmp     r0, #0                      @ test boolean result of inline
7437    beq     common_exceptionThrown      @ returned false, handle exception
7438    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7439    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7440    GOTO_OPCODE(ip)                     @ jump to next instruction
7441
7442/* ------------------------------ */
7443    .balign 64
7444.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7445/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7446    /*
7447     * invoke-direct-empty is a no-op in a "standard" interpreter.
7448     */
7449    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7450    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7451    GOTO_OPCODE(ip)                     @ execute it
7452
7453/* ------------------------------ */
7454    .balign 64
7455.L_OP_UNUSED_F1: /* 0xf1 */
7456/* File: armv5te/OP_UNUSED_F1.S */
7457/* File: armv5te/unused.S */
7458    bl      common_abort
7459
7460
7461/* ------------------------------ */
7462    .balign 64
7463.L_OP_IGET_QUICK: /* 0xf2 */
7464/* File: armv5te/OP_IGET_QUICK.S */
7465    /* For: iget-quick, iget-object-quick */
7466    /* op vA, vB, offset@CCCC */
7467    mov     r2, rINST, lsr #12          @ r2<- B
7468    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7469    FETCH(r1, 1)                        @ r1<- field byte offset
7470    cmp     r3, #0                      @ check object for null
7471    mov     r2, rINST, lsr #8           @ r2<- A(+)
7472    beq     common_errNullObject        @ object was null
7473    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7474    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7475    and     r2, r2, #15
7476    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7477    SET_VREG(r0, r2)                    @ fp[A]<- r0
7478    GOTO_OPCODE(ip)                     @ jump to next instruction
7479
7480/* ------------------------------ */
7481    .balign 64
7482.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7483/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7484    /* iget-wide-quick vA, vB, offset@CCCC */
7485    mov     r2, rINST, lsr #12          @ r2<- B
7486    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7487    FETCH(ip, 1)                        @ ip<- field byte offset
7488    cmp     r3, #0                      @ check object for null
7489    mov     r2, rINST, lsr #8           @ r2<- A(+)
7490    beq     common_errNullObject        @ object was null
7491    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7492    and     r2, r2, #15
7493    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7494    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7495    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7496    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7497    GOTO_OPCODE(ip)                     @ jump to next instruction
7498
7499/* ------------------------------ */
7500    .balign 64
7501.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7502/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7503/* File: armv5te/OP_IGET_QUICK.S */
7504    /* For: iget-quick, iget-object-quick */
7505    /* op vA, vB, offset@CCCC */
7506    mov     r2, rINST, lsr #12          @ r2<- B
7507    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7508    FETCH(r1, 1)                        @ r1<- field byte offset
7509    cmp     r3, #0                      @ check object for null
7510    mov     r2, rINST, lsr #8           @ r2<- A(+)
7511    beq     common_errNullObject        @ object was null
7512    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7513    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7514    and     r2, r2, #15
7515    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7516    SET_VREG(r0, r2)                    @ fp[A]<- r0
7517    GOTO_OPCODE(ip)                     @ jump to next instruction
7518
7519
7520/* ------------------------------ */
7521    .balign 64
7522.L_OP_IPUT_QUICK: /* 0xf5 */
7523/* File: armv5te/OP_IPUT_QUICK.S */
7524    /* For: iput-quick */
7525    /* op vA, vB, offset@CCCC */
7526    mov     r2, rINST, lsr #12          @ r2<- B
7527    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7528    FETCH(r1, 1)                        @ r1<- field byte offset
7529    cmp     r3, #0                      @ check object for null
7530    mov     r2, rINST, lsr #8           @ r2<- A(+)
7531    beq     common_errNullObject        @ object was null
7532    and     r2, r2, #15
7533    GET_VREG(r0, r2)                    @ r0<- fp[A]
7534    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7535    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7536    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7537    GOTO_OPCODE(ip)                     @ jump to next instruction
7538
7539/* ------------------------------ */
7540    .balign 64
7541.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7542/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7543    /* iput-wide-quick vA, vB, offset@CCCC */
7544    mov     r0, rINST, lsr #8           @ r0<- A(+)
7545    mov     r1, rINST, lsr #12          @ r1<- B
7546    and     r0, r0, #15
7547    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7548    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7549    cmp     r2, #0                      @ check object for null
7550    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7551    beq     common_errNullObject        @ object was null
7552    FETCH(r3, 1)                        @ r3<- field byte offset
7553    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7554    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7555    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7556    GOTO_OPCODE(ip)                     @ jump to next instruction
7557
7558/* ------------------------------ */
7559    .balign 64
7560.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7561/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7562    /* For: iput-object-quick */
7563    /* op vA, vB, offset@CCCC */
7564    mov     r2, rINST, lsr #12          @ r2<- B
7565    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7566    FETCH(r1, 1)                        @ r1<- field byte offset
7567    cmp     r3, #0                      @ check object for null
7568    mov     r2, rINST, lsr #8           @ r2<- A(+)
7569    beq     common_errNullObject        @ object was null
7570    and     r2, r2, #15
7571    GET_VREG(r0, r2)                    @ r0<- fp[A]
7572    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7573    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7574    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7575    cmp     r0, #0
7576    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7577    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7578    GOTO_OPCODE(ip)                     @ jump to next instruction
7579
7580/* ------------------------------ */
7581    .balign 64
7582.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7583/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7584    /*
7585     * Handle an optimized virtual method call.
7586     *
7587     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7588     */
7589    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7590    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7591    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7592    FETCH(r1, 1)                        @ r1<- BBBB
7593    .if     (!0)
7594    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7595    .endif
7596    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7597    cmp     r2, #0                      @ is "this" null?
7598    beq     common_errNullObject        @ null "this", throw exception
7599    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7600    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7601    EXPORT_PC()                         @ invoke must export
7602    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7603    bl      common_invokeMethodNoRange @ continue on
7604
7605/* ------------------------------ */
7606    .balign 64
7607.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7608/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7609/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7610    /*
7611     * Handle an optimized virtual method call.
7612     *
7613     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7614     */
7615    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7616    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7617    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7618    FETCH(r1, 1)                        @ r1<- BBBB
7619    .if     (!1)
7620    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7621    .endif
7622    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7623    cmp     r2, #0                      @ is "this" null?
7624    beq     common_errNullObject        @ null "this", throw exception
7625    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7626    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7627    EXPORT_PC()                         @ invoke must export
7628    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7629    bl      common_invokeMethodRange @ continue on
7630
7631
7632/* ------------------------------ */
7633    .balign 64
7634.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7635/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7636    /*
7637     * Handle an optimized "super" method call.
7638     *
7639     * for: [opt] invoke-super-quick, invoke-super-quick/range
7640     */
7641    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7642    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7643    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7644    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7645    .if     (!0)
7646    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7647    .endif
7648    FETCH(r1, 1)                        @ r1<- BBBB
7649    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7650    EXPORT_PC()                         @ must export for invoke
7651    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7652    GET_VREG(r3, r10)                   @ r3<- "this"
7653    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7654    cmp     r3, #0                      @ null "this" ref?
7655    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7656    beq     common_errNullObject        @ "this" is null, throw exception
7657    bl      common_invokeMethodNoRange @ continue on
7658
7659/* ------------------------------ */
7660    .balign 64
7661.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7662/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7663/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7664    /*
7665     * Handle an optimized "super" method call.
7666     *
7667     * for: [opt] invoke-super-quick, invoke-super-quick/range
7668     */
7669    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7670    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7671    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7672    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7673    .if     (!1)
7674    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7675    .endif
7676    FETCH(r1, 1)                        @ r1<- BBBB
7677    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7678    EXPORT_PC()                         @ must export for invoke
7679    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7680    GET_VREG(r3, r10)                   @ r3<- "this"
7681    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7682    cmp     r3, #0                      @ null "this" ref?
7683    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7684    beq     common_errNullObject        @ "this" is null, throw exception
7685    bl      common_invokeMethodRange @ continue on
7686
7687
7688/* ------------------------------ */
7689    .balign 64
7690.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7691/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7692/* File: armv5te/OP_IPUT_OBJECT.S */
7693    /*
7694     * 32-bit instance field put.
7695     *
7696     * for: iput-object, iput-object-volatile
7697     */
7698    /* op vA, vB, field@CCCC */
7699    mov     r0, rINST, lsr #12          @ r0<- B
7700    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7701    FETCH(r1, 1)                        @ r1<- field ref CCCC
7702    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7703    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7704    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7705    cmp     r0, #0                      @ is resolved entry null?
7706    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
77078:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7708    EXPORT_PC()                         @ resolve() could throw
7709    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7710    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7711    cmp     r0, #0                      @ success?
7712    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7713    b       common_exceptionThrown
7714
7715
7716/* ------------------------------ */
7717    .balign 64
7718.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7719/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7720/* File: armv5te/OP_SGET.S */
7721    /*
7722     * General 32-bit SGET handler.
7723     *
7724     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7725     */
7726    /* op vAA, field@BBBB */
7727    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7728    FETCH(r1, 1)                        @ r1<- field ref BBBB
7729    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7730    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7731    cmp     r0, #0                      @ is resolved entry null?
7732    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7733.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7734    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7735    SMP_DMB                            @ acquiring load
7736    mov     r2, rINST, lsr #8           @ r2<- AA
7737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7738    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7739    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7740    GOTO_OPCODE(ip)                     @ jump to next instruction
7741
7742
7743/* ------------------------------ */
7744    .balign 64
7745.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7746/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7747/* File: armv5te/OP_SPUT_OBJECT.S */
7748    /*
7749     * 32-bit SPUT handler for objects
7750     *
7751     * for: sput-object, sput-object-volatile
7752     */
7753    /* op vAA, field@BBBB */
7754    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7755    FETCH(r1, 1)                        @ r1<- field ref BBBB
7756    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7757    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7758    cmp     r0, #0                      @ is resolved entry null?
7759    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7760    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
7761    EXPORT_PC()                         @ resolve() could throw, so export now
7762    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
7763    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7764    cmp     r0, #0                      @ success?
7765    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7766    b       common_exceptionThrown      @ no, handle exception
7767
7768
7769
7770/* ------------------------------ */
7771    .balign 64
7772.L_OP_UNUSED_FF: /* 0xff */
7773/* File: armv5te/OP_UNUSED_FF.S */
7774/* File: armv5te/unused.S */
7775    bl      common_abort
7776
7777
7778
7779    .balign 64
7780    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7781    .global dvmAsmInstructionEnd
7782dvmAsmInstructionEnd:
7783
7784/*
7785 * ===========================================================================
7786 *  Sister implementations
7787 * ===========================================================================
7788 */
7789    .global dvmAsmSisterStart
7790    .type   dvmAsmSisterStart, %function
7791    .text
7792    .balign 4
7793dvmAsmSisterStart:
7794
7795/* continuation for OP_CONST_STRING */
7796
7797    /*
7798     * Continuation if the String has not yet been resolved.
7799     *  r1: BBBB (String ref)
7800     *  r9: target register
7801     */
7802.LOP_CONST_STRING_resolve:
7803    EXPORT_PC()
7804    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7805    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7806    bl      dvmResolveString            @ r0<- String reference
7807    cmp     r0, #0                      @ failed?
7808    beq     common_exceptionThrown      @ yup, handle the exception
7809    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7810    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7811    SET_VREG(r0, r9)                    @ vAA<- r0
7812    GOTO_OPCODE(ip)                     @ jump to next instruction
7813
7814/* continuation for OP_CONST_STRING_JUMBO */
7815
7816    /*
7817     * Continuation if the String has not yet been resolved.
7818     *  r1: BBBBBBBB (String ref)
7819     *  r9: target register
7820     */
7821.LOP_CONST_STRING_JUMBO_resolve:
7822    EXPORT_PC()
7823    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7824    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7825    bl      dvmResolveString            @ r0<- String reference
7826    cmp     r0, #0                      @ failed?
7827    beq     common_exceptionThrown      @ yup, handle the exception
7828    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7829    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7830    SET_VREG(r0, r9)                    @ vAA<- r0
7831    GOTO_OPCODE(ip)                     @ jump to next instruction
7832
7833/* continuation for OP_CONST_CLASS */
7834
7835    /*
7836     * Continuation if the Class has not yet been resolved.
7837     *  r1: BBBB (Class ref)
7838     *  r9: target register
7839     */
7840.LOP_CONST_CLASS_resolve:
7841    EXPORT_PC()
7842    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7843    mov     r2, #1                      @ r2<- true
7844    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7845    bl      dvmResolveClass             @ r0<- Class reference
7846    cmp     r0, #0                      @ failed?
7847    beq     common_exceptionThrown      @ yup, handle the exception
7848    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7849    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7850    SET_VREG(r0, r9)                    @ vAA<- r0
7851    GOTO_OPCODE(ip)                     @ jump to next instruction
7852
7853/* continuation for OP_CHECK_CAST */
7854
7855    /*
7856     * Trivial test failed, need to perform full check.  This is common.
7857     *  r0 holds obj->clazz
7858     *  r1 holds class resolved from BBBB
7859     *  r9 holds object
7860     */
7861.LOP_CHECK_CAST_fullcheck:
7862    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7863    cmp     r0, #0                      @ failed?
7864    bne     .LOP_CHECK_CAST_okay            @ no, success
7865
7866    @ A cast has failed.  We need to throw a ClassCastException with the
7867    @ class of the object that failed to be cast.
7868    EXPORT_PC()                         @ about to throw
7869    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7870    ldr     r0, .LstrClassCastExceptionPtr
7871    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7872    bl      dvmThrowExceptionWithClassMessage
7873    b       common_exceptionThrown
7874
7875    /*
7876     * Resolution required.  This is the least-likely path.
7877     *
7878     *  r2 holds BBBB
7879     *  r9 holds object
7880     */
7881.LOP_CHECK_CAST_resolve:
7882    EXPORT_PC()                         @ resolve() could throw
7883    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7884    mov     r1, r2                      @ r1<- BBBB
7885    mov     r2, #0                      @ r2<- false
7886    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7887    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7888    cmp     r0, #0                      @ got null?
7889    beq     common_exceptionThrown      @ yes, handle exception
7890    mov     r1, r0                      @ r1<- class resolved from BBB
7891    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7892    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7893
7894.LstrClassCastExceptionPtr:
7895    .word   .LstrClassCastException
7896
7897/* continuation for OP_INSTANCE_OF */
7898
7899    /*
7900     * Trivial test failed, need to perform full check.  This is common.
7901     *  r0 holds obj->clazz
7902     *  r1 holds class resolved from BBBB
7903     *  r9 holds A
7904     */
7905.LOP_INSTANCE_OF_fullcheck:
7906    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7907    @ fall through to OP_INSTANCE_OF_store
7908
7909    /*
7910     * r0 holds boolean result
7911     * r9 holds A
7912     */
7913.LOP_INSTANCE_OF_store:
7914    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7915    SET_VREG(r0, r9)                    @ vA<- r0
7916    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7917    GOTO_OPCODE(ip)                     @ jump to next instruction
7918
7919    /*
7920     * Trivial test succeeded, save and bail.
7921     *  r9 holds A
7922     */
7923.LOP_INSTANCE_OF_trivial:
7924    mov     r0, #1                      @ indicate success
7925    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7926    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7927    SET_VREG(r0, r9)                    @ vA<- r0
7928    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7929    GOTO_OPCODE(ip)                     @ jump to next instruction
7930
7931    /*
7932     * Resolution required.  This is the least-likely path.
7933     *
7934     *  r3 holds BBBB
7935     *  r9 holds A
7936     */
7937.LOP_INSTANCE_OF_resolve:
7938    EXPORT_PC()                         @ resolve() could throw
7939    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7940    mov     r1, r3                      @ r1<- BBBB
7941    mov     r2, #1                      @ r2<- true
7942    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7943    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7944    cmp     r0, #0                      @ got null?
7945    beq     common_exceptionThrown      @ yes, handle exception
7946    mov     r1, r0                      @ r1<- class resolved from BBB
7947    mov     r3, rINST, lsr #12          @ r3<- B
7948    GET_VREG(r0, r3)                    @ r0<- vB (object)
7949    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7950    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7951
7952/* continuation for OP_NEW_INSTANCE */
7953
7954    .balign 32                          @ minimize cache lines
7955.LOP_NEW_INSTANCE_finish: @ r0=new object
7956    mov     r3, rINST, lsr #8           @ r3<- AA
7957    cmp     r0, #0                      @ failed?
7958    beq     common_exceptionThrown      @ yes, handle the exception
7959    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7960    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7961    SET_VREG(r0, r3)                    @ vAA<- r0
7962    GOTO_OPCODE(ip)                     @ jump to next instruction
7963
7964    /*
7965     * Class initialization required.
7966     *
7967     *  r0 holds class object
7968     */
7969.LOP_NEW_INSTANCE_needinit:
7970    mov     r9, r0                      @ save r0
7971    bl      dvmInitClass                @ initialize class
7972    cmp     r0, #0                      @ check boolean result
7973    mov     r0, r9                      @ restore r0
7974    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7975    b       common_exceptionThrown      @ failed, deal with init exception
7976
7977    /*
7978     * Resolution required.  This is the least-likely path.
7979     *
7980     *  r1 holds BBBB
7981     */
7982.LOP_NEW_INSTANCE_resolve:
7983    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7984    mov     r2, #0                      @ r2<- false
7985    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7986    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7987    cmp     r0, #0                      @ got null?
7988    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7989    b       common_exceptionThrown      @ yes, handle exception
7990
7991.LstrInstantiationErrorPtr:
7992    .word   .LstrInstantiationError
7993
7994/* continuation for OP_NEW_ARRAY */
7995
7996
7997    /*
7998     * Resolve class.  (This is an uncommon case.)
7999     *
8000     *  r1 holds array length
8001     *  r2 holds class ref CCCC
8002     */
8003.LOP_NEW_ARRAY_resolve:
8004    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8005    mov     r9, r1                      @ r9<- length (save)
8006    mov     r1, r2                      @ r1<- CCCC
8007    mov     r2, #0                      @ r2<- false
8008    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8009    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8010    cmp     r0, #0                      @ got null?
8011    mov     r1, r9                      @ r1<- length (restore)
8012    beq     common_exceptionThrown      @ yes, handle exception
8013    @ fall through to OP_NEW_ARRAY_finish
8014
8015    /*
8016     * Finish allocation.
8017     *
8018     *  r0 holds class
8019     *  r1 holds array length
8020     */
8021.LOP_NEW_ARRAY_finish:
8022    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8023    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8024    cmp     r0, #0                      @ failed?
8025    mov     r2, rINST, lsr #8           @ r2<- A+
8026    beq     common_exceptionThrown      @ yes, handle the exception
8027    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8028    and     r2, r2, #15                 @ r2<- A
8029    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8030    SET_VREG(r0, r2)                    @ vA<- r0
8031    GOTO_OPCODE(ip)                     @ jump to next instruction
8032
8033/* continuation for OP_FILLED_NEW_ARRAY */
8034
8035    /*
8036     * On entry:
8037     *  r0 holds array class
8038     *  r10 holds AA or BA
8039     */
8040.LOP_FILLED_NEW_ARRAY_continue:
8041    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8042    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8043    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8044    .if     0
8045    mov     r1, r10                     @ r1<- AA (length)
8046    .else
8047    mov     r1, r10, lsr #4             @ r1<- B (length)
8048    .endif
8049    cmp     rINST, #'I'                 @ array of ints?
8050    cmpne   rINST, #'L'                 @ array of objects?
8051    cmpne   rINST, #'['                 @ array of arrays?
8052    mov     r9, r1                      @ save length in r9
8053    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8054    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8055    cmp     r0, #0                      @ null return?
8056    beq     common_exceptionThrown      @ alloc failed, handle exception
8057
8058    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8059    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8060    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8061    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8062    subs    r9, r9, #1                  @ length--, check for neg
8063    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8064    bmi     2f                          @ was zero, bail
8065
8066    @ copy values from registers into the array
8067    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8068    .if     0
8069    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80701:  ldr     r3, [r2], #4                @ r3<- *r2++
8071    subs    r9, r9, #1                  @ count--
8072    str     r3, [r0], #4                @ *contents++ = vX
8073    bpl     1b
8074    @ continue at 2
8075    .else
8076    cmp     r9, #4                      @ length was initially 5?
8077    and     r2, r10, #15                @ r2<- A
8078    bne     1f                          @ <= 4 args, branch
8079    GET_VREG(r3, r2)                    @ r3<- vA
8080    sub     r9, r9, #1                  @ count--
8081    str     r3, [r0, #16]               @ contents[4] = vA
80821:  and     r2, r1, #15                 @ r2<- F/E/D/C
8083    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8084    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8085    subs    r9, r9, #1                  @ count--
8086    str     r3, [r0], #4                @ *contents++ = vX
8087    bpl     1b
8088    @ continue at 2
8089    .endif
8090
80912:
8092    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8093    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8094    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8095    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8096    cmp     r1, #'I'                         @ Is int array?
8097    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8098    GOTO_OPCODE(ip)                          @ execute it
8099
8100    /*
8101     * Throw an exception indicating that we have not implemented this
8102     * mode of filled-new-array.
8103     */
8104.LOP_FILLED_NEW_ARRAY_notimpl:
8105    ldr     r0, .L_strInternalError
8106    ldr     r1, .L_strFilledNewArrayNotImpl
8107    bl      dvmThrowException
8108    b       common_exceptionThrown
8109
8110    .if     (!0)                 @ define in one or the other, not both
8111.L_strFilledNewArrayNotImpl:
8112    .word   .LstrFilledNewArrayNotImpl
8113.L_strInternalError:
8114    .word   .LstrInternalError
8115    .endif
8116
8117/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8118
8119    /*
8120     * On entry:
8121     *  r0 holds array class
8122     *  r10 holds AA or BA
8123     */
8124.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8125    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8126    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8127    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8128    .if     1
8129    mov     r1, r10                     @ r1<- AA (length)
8130    .else
8131    mov     r1, r10, lsr #4             @ r1<- B (length)
8132    .endif
8133    cmp     rINST, #'I'                 @ array of ints?
8134    cmpne   rINST, #'L'                 @ array of objects?
8135    cmpne   rINST, #'['                 @ array of arrays?
8136    mov     r9, r1                      @ save length in r9
8137    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8138    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8139    cmp     r0, #0                      @ null return?
8140    beq     common_exceptionThrown      @ alloc failed, handle exception
8141
8142    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8143    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8144    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8145    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8146    subs    r9, r9, #1                  @ length--, check for neg
8147    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8148    bmi     2f                          @ was zero, bail
8149
8150    @ copy values from registers into the array
8151    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8152    .if     1
8153    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81541:  ldr     r3, [r2], #4                @ r3<- *r2++
8155    subs    r9, r9, #1                  @ count--
8156    str     r3, [r0], #4                @ *contents++ = vX
8157    bpl     1b
8158    @ continue at 2
8159    .else
8160    cmp     r9, #4                      @ length was initially 5?
8161    and     r2, r10, #15                @ r2<- A
8162    bne     1f                          @ <= 4 args, branch
8163    GET_VREG(r3, r2)                    @ r3<- vA
8164    sub     r9, r9, #1                  @ count--
8165    str     r3, [r0, #16]               @ contents[4] = vA
81661:  and     r2, r1, #15                 @ r2<- F/E/D/C
8167    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8168    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8169    subs    r9, r9, #1                  @ count--
8170    str     r3, [r0], #4                @ *contents++ = vX
8171    bpl     1b
8172    @ continue at 2
8173    .endif
8174
81752:
8176    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8177    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8178    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8179    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8180    cmp     r1, #'I'                         @ Is int array?
8181    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8182    GOTO_OPCODE(ip)                          @ execute it
8183
8184    /*
8185     * Throw an exception indicating that we have not implemented this
8186     * mode of filled-new-array.
8187     */
8188.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8189    ldr     r0, .L_strInternalError
8190    ldr     r1, .L_strFilledNewArrayNotImpl
8191    bl      dvmThrowException
8192    b       common_exceptionThrown
8193
8194    .if     (!1)                 @ define in one or the other, not both
8195.L_strFilledNewArrayNotImpl:
8196    .word   .LstrFilledNewArrayNotImpl
8197.L_strInternalError:
8198    .word   .LstrInternalError
8199    .endif
8200
8201/* continuation for OP_CMPL_FLOAT */
8202.LOP_CMPL_FLOAT_finish:
8203    SET_VREG(r0, r9)                    @ vAA<- r0
8204    GOTO_OPCODE(ip)                     @ jump to next instruction
8205
8206/* continuation for OP_CMPG_FLOAT */
8207.LOP_CMPG_FLOAT_finish:
8208    SET_VREG(r0, r9)                    @ vAA<- r0
8209    GOTO_OPCODE(ip)                     @ jump to next instruction
8210
8211/* continuation for OP_CMPL_DOUBLE */
8212.LOP_CMPL_DOUBLE_finish:
8213    SET_VREG(r0, r9)                    @ vAA<- r0
8214    GOTO_OPCODE(ip)                     @ jump to next instruction
8215
8216/* continuation for OP_CMPG_DOUBLE */
8217.LOP_CMPG_DOUBLE_finish:
8218    SET_VREG(r0, r9)                    @ vAA<- r0
8219    GOTO_OPCODE(ip)                     @ jump to next instruction
8220
8221/* continuation for OP_CMP_LONG */
8222
8223.LOP_CMP_LONG_less:
8224    mvn     r1, #0                      @ r1<- -1
8225    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8226    @ instead, we just replicate the tail end.
8227    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8228    SET_VREG(r1, r9)                    @ vAA<- r1
8229    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8230    GOTO_OPCODE(ip)                     @ jump to next instruction
8231
8232.LOP_CMP_LONG_greater:
8233    mov     r1, #1                      @ r1<- 1
8234    @ fall through to _finish
8235
8236.LOP_CMP_LONG_finish:
8237    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8238    SET_VREG(r1, r9)                    @ vAA<- r1
8239    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8240    GOTO_OPCODE(ip)                     @ jump to next instruction
8241
8242/* continuation for OP_AGET_WIDE */
8243
8244.LOP_AGET_WIDE_finish:
8245    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8246    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8247    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8248    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8249    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8250    GOTO_OPCODE(ip)                     @ jump to next instruction
8251
8252/* continuation for OP_APUT_WIDE */
8253
8254.LOP_APUT_WIDE_finish:
8255    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8256    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8257    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8258    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8259    GOTO_OPCODE(ip)                     @ jump to next instruction
8260
8261/* continuation for OP_APUT_OBJECT */
8262    /*
8263     * On entry:
8264     *  rINST = vBB (arrayObj)
8265     *  r9 = vAA (obj)
8266     *  r10 = offset into array (vBB + vCC * width)
8267     */
8268.LOP_APUT_OBJECT_finish:
8269    cmp     r9, #0                      @ storing null reference?
8270    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8271    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8272    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8273    bl      dvmCanPutArrayElement       @ test object type vs. array type
8274    cmp     r0, #0                      @ okay?
8275    beq     common_errArrayStore        @ no
8276    mov     r1, rINST                   @ r1<- arrayObj
8277    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8278    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8279    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8280    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8281    str     r9, [r10]                   @ vBB[vCC]<- vAA
8282    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8283    GOTO_OPCODE(ip)                     @ jump to next instruction
8284.LOP_APUT_OBJECT_skip_check:
8285    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8286    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8287    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8288    GOTO_OPCODE(ip)                     @ jump to next instruction
8289
8290/* continuation for OP_IGET */
8291
8292    /*
8293     * Currently:
8294     *  r0 holds resolved field
8295     *  r9 holds object
8296     */
8297.LOP_IGET_finish:
8298    @bl      common_squeak0
8299    cmp     r9, #0                      @ check object for null
8300    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8301    beq     common_errNullObject        @ object was null
8302    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8303    @ no-op                             @ acquiring load
8304    mov     r2, rINST, lsr #8           @ r2<- A+
8305    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8306    and     r2, r2, #15                 @ r2<- A
8307    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8308    SET_VREG(r0, r2)                    @ fp[A]<- r0
8309    GOTO_OPCODE(ip)                     @ jump to next instruction
8310
8311/* continuation for OP_IGET_WIDE */
8312
8313    /*
8314     * Currently:
8315     *  r0 holds resolved field
8316     *  r9 holds object
8317     */
8318.LOP_IGET_WIDE_finish:
8319    cmp     r9, #0                      @ check object for null
8320    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8321    beq     common_errNullObject        @ object was null
8322    .if     0
8323    add     r0, r9, r3                  @ r0<- address of field
8324    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8325    .else
8326    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8327    .endif
8328    mov     r2, rINST, lsr #8           @ r2<- A+
8329    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8330    and     r2, r2, #15                 @ r2<- A
8331    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8332    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8333    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8334    GOTO_OPCODE(ip)                     @ jump to next instruction
8335
8336/* continuation for OP_IGET_OBJECT */
8337
8338    /*
8339     * Currently:
8340     *  r0 holds resolved field
8341     *  r9 holds object
8342     */
8343.LOP_IGET_OBJECT_finish:
8344    @bl      common_squeak0
8345    cmp     r9, #0                      @ check object for null
8346    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8347    beq     common_errNullObject        @ object was null
8348    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8349    @ no-op                             @ acquiring load
8350    mov     r2, rINST, lsr #8           @ r2<- A+
8351    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8352    and     r2, r2, #15                 @ r2<- A
8353    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8354    SET_VREG(r0, r2)                    @ fp[A]<- r0
8355    GOTO_OPCODE(ip)                     @ jump to next instruction
8356
8357/* continuation for OP_IGET_BOOLEAN */
8358
8359    /*
8360     * Currently:
8361     *  r0 holds resolved field
8362     *  r9 holds object
8363     */
8364.LOP_IGET_BOOLEAN_finish:
8365    @bl      common_squeak1
8366    cmp     r9, #0                      @ check object for null
8367    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8368    beq     common_errNullObject        @ object was null
8369    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8370    @ no-op                             @ acquiring load
8371    mov     r2, rINST, lsr #8           @ r2<- A+
8372    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8373    and     r2, r2, #15                 @ r2<- A
8374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8375    SET_VREG(r0, r2)                    @ fp[A]<- r0
8376    GOTO_OPCODE(ip)                     @ jump to next instruction
8377
8378/* continuation for OP_IGET_BYTE */
8379
8380    /*
8381     * Currently:
8382     *  r0 holds resolved field
8383     *  r9 holds object
8384     */
8385.LOP_IGET_BYTE_finish:
8386    @bl      common_squeak2
8387    cmp     r9, #0                      @ check object for null
8388    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8389    beq     common_errNullObject        @ object was null
8390    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8391    @ no-op                             @ acquiring load
8392    mov     r2, rINST, lsr #8           @ r2<- A+
8393    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8394    and     r2, r2, #15                 @ r2<- A
8395    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8396    SET_VREG(r0, r2)                    @ fp[A]<- r0
8397    GOTO_OPCODE(ip)                     @ jump to next instruction
8398
8399/* continuation for OP_IGET_CHAR */
8400
8401    /*
8402     * Currently:
8403     *  r0 holds resolved field
8404     *  r9 holds object
8405     */
8406.LOP_IGET_CHAR_finish:
8407    @bl      common_squeak3
8408    cmp     r9, #0                      @ check object for null
8409    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8410    beq     common_errNullObject        @ object was null
8411    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8412    @ no-op                             @ acquiring load
8413    mov     r2, rINST, lsr #8           @ r2<- A+
8414    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8415    and     r2, r2, #15                 @ r2<- A
8416    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8417    SET_VREG(r0, r2)                    @ fp[A]<- r0
8418    GOTO_OPCODE(ip)                     @ jump to next instruction
8419
8420/* continuation for OP_IGET_SHORT */
8421
8422    /*
8423     * Currently:
8424     *  r0 holds resolved field
8425     *  r9 holds object
8426     */
8427.LOP_IGET_SHORT_finish:
8428    @bl      common_squeak4
8429    cmp     r9, #0                      @ check object for null
8430    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8431    beq     common_errNullObject        @ object was null
8432    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8433    @ no-op                             @ acquiring load
8434    mov     r2, rINST, lsr #8           @ r2<- A+
8435    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8436    and     r2, r2, #15                 @ r2<- A
8437    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8438    SET_VREG(r0, r2)                    @ fp[A]<- r0
8439    GOTO_OPCODE(ip)                     @ jump to next instruction
8440
8441/* continuation for OP_IPUT */
8442
8443    /*
8444     * Currently:
8445     *  r0 holds resolved field
8446     *  r9 holds object
8447     */
8448.LOP_IPUT_finish:
8449    @bl      common_squeak0
8450    mov     r1, rINST, lsr #8           @ r1<- A+
8451    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8452    and     r1, r1, #15                 @ r1<- A
8453    cmp     r9, #0                      @ check object for null
8454    GET_VREG(r0, r1)                    @ r0<- fp[A]
8455    beq     common_errNullObject        @ object was null
8456    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8457    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8458    @ no-op                             @ releasing store
8459    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8460    GOTO_OPCODE(ip)                     @ jump to next instruction
8461
8462/* continuation for OP_IPUT_WIDE */
8463
8464    /*
8465     * Currently:
8466     *  r0 holds resolved field
8467     *  r9 holds object
8468     */
8469.LOP_IPUT_WIDE_finish:
8470    mov     r2, rINST, lsr #8           @ r2<- A+
8471    cmp     r9, #0                      @ check object for null
8472    and     r2, r2, #15                 @ r2<- A
8473    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8474    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8475    beq     common_errNullObject        @ object was null
8476    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8477    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8478    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8479    .if     0
8480    add     r2, r9, r3                  @ r2<- target address
8481    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8482    .else
8483    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8484    .endif
8485    GOTO_OPCODE(r10)                    @ jump to next instruction
8486
8487/* continuation for OP_IPUT_OBJECT */
8488
8489    /*
8490     * Currently:
8491     *  r0 holds resolved field
8492     *  r9 holds object
8493     */
8494.LOP_IPUT_OBJECT_finish:
8495    @bl      common_squeak0
8496    mov     r1, rINST, lsr #8           @ r1<- A+
8497    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8498    and     r1, r1, #15                 @ r1<- A
8499    cmp     r9, #0                      @ check object for null
8500    GET_VREG(r0, r1)                    @ r0<- fp[A]
8501    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8502    beq     common_errNullObject        @ object was null
8503    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8504    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8505    @ no-op                             @ releasing store
8506    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
8507    cmp     r0, #0                      @ stored a null reference?
8508    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8509    GOTO_OPCODE(ip)                     @ jump to next instruction
8510
8511/* continuation for OP_IPUT_BOOLEAN */
8512
8513    /*
8514     * Currently:
8515     *  r0 holds resolved field
8516     *  r9 holds object
8517     */
8518.LOP_IPUT_BOOLEAN_finish:
8519    @bl      common_squeak1
8520    mov     r1, rINST, lsr #8           @ r1<- A+
8521    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8522    and     r1, r1, #15                 @ r1<- A
8523    cmp     r9, #0                      @ check object for null
8524    GET_VREG(r0, r1)                    @ r0<- fp[A]
8525    beq     common_errNullObject        @ object was null
8526    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8527    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8528    @ no-op                             @ releasing store
8529    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8530    GOTO_OPCODE(ip)                     @ jump to next instruction
8531
8532/* continuation for OP_IPUT_BYTE */
8533
8534    /*
8535     * Currently:
8536     *  r0 holds resolved field
8537     *  r9 holds object
8538     */
8539.LOP_IPUT_BYTE_finish:
8540    @bl      common_squeak2
8541    mov     r1, rINST, lsr #8           @ r1<- A+
8542    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8543    and     r1, r1, #15                 @ r1<- A
8544    cmp     r9, #0                      @ check object for null
8545    GET_VREG(r0, r1)                    @ r0<- fp[A]
8546    beq     common_errNullObject        @ object was null
8547    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8548    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8549    @ no-op                             @ releasing store
8550    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8551    GOTO_OPCODE(ip)                     @ jump to next instruction
8552
8553/* continuation for OP_IPUT_CHAR */
8554
8555    /*
8556     * Currently:
8557     *  r0 holds resolved field
8558     *  r9 holds object
8559     */
8560.LOP_IPUT_CHAR_finish:
8561    @bl      common_squeak3
8562    mov     r1, rINST, lsr #8           @ r1<- A+
8563    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8564    and     r1, r1, #15                 @ r1<- A
8565    cmp     r9, #0                      @ check object for null
8566    GET_VREG(r0, r1)                    @ r0<- fp[A]
8567    beq     common_errNullObject        @ object was null
8568    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8569    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8570    @ no-op                             @ releasing store
8571    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8572    GOTO_OPCODE(ip)                     @ jump to next instruction
8573
8574/* continuation for OP_IPUT_SHORT */
8575
8576    /*
8577     * Currently:
8578     *  r0 holds resolved field
8579     *  r9 holds object
8580     */
8581.LOP_IPUT_SHORT_finish:
8582    @bl      common_squeak4
8583    mov     r1, rINST, lsr #8           @ r1<- A+
8584    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8585    and     r1, r1, #15                 @ r1<- A
8586    cmp     r9, #0                      @ check object for null
8587    GET_VREG(r0, r1)                    @ r0<- fp[A]
8588    beq     common_errNullObject        @ object was null
8589    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8591    @ no-op                             @ releasing store
8592    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8593    GOTO_OPCODE(ip)                     @ jump to next instruction
8594
8595/* continuation for OP_SGET */
8596
8597    /*
8598     * Continuation if the field has not yet been resolved.
8599     *  r1: BBBB field ref
8600     */
8601.LOP_SGET_resolve:
8602    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8603    EXPORT_PC()                         @ resolve() could throw, so export now
8604    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8605    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8606    cmp     r0, #0                      @ success?
8607    bne     .LOP_SGET_finish          @ yes, finish
8608    b       common_exceptionThrown      @ no, handle exception
8609
8610/* continuation for OP_SGET_WIDE */
8611
8612    /*
8613     * Continuation if the field has not yet been resolved.
8614     *  r1: BBBB field ref
8615     *
8616     * Returns StaticField pointer in r0.
8617     */
8618.LOP_SGET_WIDE_resolve:
8619    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8620    EXPORT_PC()                         @ resolve() could throw, so export now
8621    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8622    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8623    cmp     r0, #0                      @ success?
8624    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8625    b       common_exceptionThrown      @ no, handle exception
8626
8627/* continuation for OP_SGET_OBJECT */
8628
8629    /*
8630     * Continuation if the field has not yet been resolved.
8631     *  r1: BBBB field ref
8632     */
8633.LOP_SGET_OBJECT_resolve:
8634    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8635    EXPORT_PC()                         @ resolve() could throw, so export now
8636    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8637    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8638    cmp     r0, #0                      @ success?
8639    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8640    b       common_exceptionThrown      @ no, handle exception
8641
8642/* continuation for OP_SGET_BOOLEAN */
8643
8644    /*
8645     * Continuation if the field has not yet been resolved.
8646     *  r1: BBBB field ref
8647     */
8648.LOP_SGET_BOOLEAN_resolve:
8649    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8650    EXPORT_PC()                         @ resolve() could throw, so export now
8651    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8652    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8653    cmp     r0, #0                      @ success?
8654    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8655    b       common_exceptionThrown      @ no, handle exception
8656
8657/* continuation for OP_SGET_BYTE */
8658
8659    /*
8660     * Continuation if the field has not yet been resolved.
8661     *  r1: BBBB field ref
8662     */
8663.LOP_SGET_BYTE_resolve:
8664    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8665    EXPORT_PC()                         @ resolve() could throw, so export now
8666    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8667    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8668    cmp     r0, #0                      @ success?
8669    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8670    b       common_exceptionThrown      @ no, handle exception
8671
8672/* continuation for OP_SGET_CHAR */
8673
8674    /*
8675     * Continuation if the field has not yet been resolved.
8676     *  r1: BBBB field ref
8677     */
8678.LOP_SGET_CHAR_resolve:
8679    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8680    EXPORT_PC()                         @ resolve() could throw, so export now
8681    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8682    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8683    cmp     r0, #0                      @ success?
8684    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8685    b       common_exceptionThrown      @ no, handle exception
8686
8687/* continuation for OP_SGET_SHORT */
8688
8689    /*
8690     * Continuation if the field has not yet been resolved.
8691     *  r1: BBBB field ref
8692     */
8693.LOP_SGET_SHORT_resolve:
8694    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8695    EXPORT_PC()                         @ resolve() could throw, so export now
8696    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8697    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8698    cmp     r0, #0                      @ success?
8699    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8700    b       common_exceptionThrown      @ no, handle exception
8701
8702/* continuation for OP_SPUT */
8703
8704    /*
8705     * Continuation if the field has not yet been resolved.
8706     *  r1: BBBB field ref
8707     */
8708.LOP_SPUT_resolve:
8709    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8710    EXPORT_PC()                         @ resolve() could throw, so export now
8711    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8712    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8713    cmp     r0, #0                      @ success?
8714    bne     .LOP_SPUT_finish          @ yes, finish
8715    b       common_exceptionThrown      @ no, handle exception
8716
8717/* continuation for OP_SPUT_WIDE */
8718
8719    /*
8720     * Continuation if the field has not yet been resolved.
8721     *  r1: BBBB field ref
8722     *  r9: &fp[AA]
8723     *
8724     * Returns StaticField pointer in r2.
8725     */
8726.LOP_SPUT_WIDE_resolve:
8727    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8728    EXPORT_PC()                         @ resolve() could throw, so export now
8729    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8730    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8731    cmp     r0, #0                      @ success?
8732    mov     r2, r0                      @ copy to r2
8733    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8734    b       common_exceptionThrown      @ no, handle exception
8735
8736/* continuation for OP_SPUT_OBJECT */
8737.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8738    mov     r2, rINST, lsr #8           @ r2<- AA
8739    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8740    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8741    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8742    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
8743    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8744    @ no-op                             @ releasing store
8745    str     r1, [r0, #offStaticField_value]  @ field<- vAA
8746    cmp     r1, #0                      @ stored a null object?
8747    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
8748    GOTO_OPCODE(ip)                     @ jump to next instruction
8749
8750/* continuation for OP_SPUT_BOOLEAN */
8751
8752    /*
8753     * Continuation if the field has not yet been resolved.
8754     *  r1: BBBB field ref
8755     */
8756.LOP_SPUT_BOOLEAN_resolve:
8757    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8758    EXPORT_PC()                         @ resolve() could throw, so export now
8759    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8760    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8761    cmp     r0, #0                      @ success?
8762    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8763    b       common_exceptionThrown      @ no, handle exception
8764
8765/* continuation for OP_SPUT_BYTE */
8766
8767    /*
8768     * Continuation if the field has not yet been resolved.
8769     *  r1: BBBB field ref
8770     */
8771.LOP_SPUT_BYTE_resolve:
8772    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8773    EXPORT_PC()                         @ resolve() could throw, so export now
8774    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8775    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8776    cmp     r0, #0                      @ success?
8777    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8778    b       common_exceptionThrown      @ no, handle exception
8779
8780/* continuation for OP_SPUT_CHAR */
8781
8782    /*
8783     * Continuation if the field has not yet been resolved.
8784     *  r1: BBBB field ref
8785     */
8786.LOP_SPUT_CHAR_resolve:
8787    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8788    EXPORT_PC()                         @ resolve() could throw, so export now
8789    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8790    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8791    cmp     r0, #0                      @ success?
8792    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8793    b       common_exceptionThrown      @ no, handle exception
8794
8795/* continuation for OP_SPUT_SHORT */
8796
8797    /*
8798     * Continuation if the field has not yet been resolved.
8799     *  r1: BBBB field ref
8800     */
8801.LOP_SPUT_SHORT_resolve:
8802    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8803    EXPORT_PC()                         @ resolve() could throw, so export now
8804    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8805    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8806    cmp     r0, #0                      @ success?
8807    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8808    b       common_exceptionThrown      @ no, handle exception
8809
8810/* continuation for OP_INVOKE_VIRTUAL */
8811
8812    /*
8813     * At this point:
8814     *  r0 = resolved base method
8815     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8816     */
8817.LOP_INVOKE_VIRTUAL_continue:
8818    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8819    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8820    cmp     r1, #0                      @ is "this" null?
8821    beq     common_errNullObject        @ null "this", throw exception
8822    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8823    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8824    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8825    bl      common_invokeMethodNoRange @ continue on
8826
8827/* continuation for OP_INVOKE_SUPER */
8828
8829    /*
8830     * At this point:
8831     *  r0 = resolved base method
8832     *  r9 = method->clazz
8833     */
8834.LOP_INVOKE_SUPER_continue:
8835    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8836    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8837    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8838    EXPORT_PC()                         @ must export for invoke
8839    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8840    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8841    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8842    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8843    bl      common_invokeMethodNoRange @ continue on
8844
8845.LOP_INVOKE_SUPER_resolve:
8846    mov     r0, r9                      @ r0<- method->clazz
8847    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8848    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8849    cmp     r0, #0                      @ got null?
8850    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8851    b       common_exceptionThrown      @ yes, handle exception
8852
8853    /*
8854     * Throw a NoSuchMethodError with the method name as the message.
8855     *  r0 = resolved base method
8856     */
8857.LOP_INVOKE_SUPER_nsm:
8858    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8859    b       common_errNoSuchMethod
8860
8861/* continuation for OP_INVOKE_DIRECT */
8862
8863    /*
8864     * On entry:
8865     *  r1 = reference (BBBB or CCCC)
8866     *  r10 = "this" register
8867     */
8868.LOP_INVOKE_DIRECT_resolve:
8869    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8870    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8871    mov     r2, #METHOD_DIRECT          @ resolver method type
8872    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8873    cmp     r0, #0                      @ got null?
8874    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8875    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8876    b       common_exceptionThrown      @ yes, handle exception
8877
8878/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8879
8880    /*
8881     * At this point:
8882     *  r0 = resolved base method
8883     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8884     */
8885.LOP_INVOKE_VIRTUAL_RANGE_continue:
8886    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8887    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8888    cmp     r1, #0                      @ is "this" null?
8889    beq     common_errNullObject        @ null "this", throw exception
8890    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8891    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8892    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8893    bl      common_invokeMethodRange @ continue on
8894
8895/* continuation for OP_INVOKE_SUPER_RANGE */
8896
8897    /*
8898     * At this point:
8899     *  r0 = resolved base method
8900     *  r9 = method->clazz
8901     */
8902.LOP_INVOKE_SUPER_RANGE_continue:
8903    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8904    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8905    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8906    EXPORT_PC()                         @ must export for invoke
8907    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8908    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8909    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8910    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8911    bl      common_invokeMethodRange @ continue on
8912
8913.LOP_INVOKE_SUPER_RANGE_resolve:
8914    mov     r0, r9                      @ r0<- method->clazz
8915    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8916    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8917    cmp     r0, #0                      @ got null?
8918    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8919    b       common_exceptionThrown      @ yes, handle exception
8920
8921    /*
8922     * Throw a NoSuchMethodError with the method name as the message.
8923     *  r0 = resolved base method
8924     */
8925.LOP_INVOKE_SUPER_RANGE_nsm:
8926    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8927    b       common_errNoSuchMethod
8928
8929/* continuation for OP_INVOKE_DIRECT_RANGE */
8930
8931    /*
8932     * On entry:
8933     *  r1 = reference (BBBB or CCCC)
8934     *  r10 = "this" register
8935     */
8936.LOP_INVOKE_DIRECT_RANGE_resolve:
8937    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8938    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8939    mov     r2, #METHOD_DIRECT          @ resolver method type
8940    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8941    cmp     r0, #0                      @ got null?
8942    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8943    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8944    b       common_exceptionThrown      @ yes, handle exception
8945
8946/* continuation for OP_FLOAT_TO_LONG */
8947/*
8948 * Convert the float in r0 to a long in r0/r1.
8949 *
8950 * We have to clip values to long min/max per the specification.  The
8951 * expected common case is a "reasonable" value that converts directly
8952 * to modest integer.  The EABI convert function isn't doing this for us.
8953 */
8954f2l_doconv:
8955    stmfd   sp!, {r4, lr}
8956    mov     r1, #0x5f000000             @ (float)maxlong
8957    mov     r4, r0
8958    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8959    cmp     r0, #0                      @ nonzero == yes
8960    mvnne   r0, #0                      @ return maxlong (7fffffff)
8961    mvnne   r1, #0x80000000
8962    ldmnefd sp!, {r4, pc}
8963
8964    mov     r0, r4                      @ recover arg
8965    mov     r1, #0xdf000000             @ (float)minlong
8966    bl      __aeabi_fcmple              @ is arg <= minlong?
8967    cmp     r0, #0                      @ nonzero == yes
8968    movne   r0, #0                      @ return minlong (80000000)
8969    movne   r1, #0x80000000
8970    ldmnefd sp!, {r4, pc}
8971
8972    mov     r0, r4                      @ recover arg
8973    mov     r1, r4
8974    bl      __aeabi_fcmpeq              @ is arg == self?
8975    cmp     r0, #0                      @ zero == no
8976    moveq   r1, #0                      @ return zero for NaN
8977    ldmeqfd sp!, {r4, pc}
8978
8979    mov     r0, r4                      @ recover arg
8980    bl      __aeabi_f2lz                @ convert float to long
8981    ldmfd   sp!, {r4, pc}
8982
8983/* continuation for OP_DOUBLE_TO_LONG */
8984/*
8985 * Convert the double in r0/r1 to a long in r0/r1.
8986 *
8987 * We have to clip values to long min/max per the specification.  The
8988 * expected common case is a "reasonable" value that converts directly
8989 * to modest integer.  The EABI convert function isn't doing this for us.
8990 */
8991d2l_doconv:
8992    stmfd   sp!, {r4, r5, lr}           @ save regs
8993    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8994    add     r3, #0x00e00000             @  0x43e00000
8995    mov     r2, #0                      @ maxlong, as a double (low word)
8996    sub     sp, sp, #4                  @ align for EABI
8997    mov     r4, r0                      @ save a copy of r0
8998    mov     r5, r1                      @  and r1
8999    bl      __aeabi_dcmpge              @ is arg >= maxlong?
9000    cmp     r0, #0                      @ nonzero == yes
9001    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9002    mvnne   r1, #0x80000000
9003    bne     1f
9004
9005    mov     r0, r4                      @ recover arg
9006    mov     r1, r5
9007    mov     r3, #0xc3000000             @ minlong, as a double (high word)
9008    add     r3, #0x00e00000             @  0xc3e00000
9009    mov     r2, #0                      @ minlong, as a double (low word)
9010    bl      __aeabi_dcmple              @ is arg <= minlong?
9011    cmp     r0, #0                      @ nonzero == yes
9012    movne   r0, #0                      @ return minlong (8000000000000000)
9013    movne   r1, #0x80000000
9014    bne     1f
9015
9016    mov     r0, r4                      @ recover arg
9017    mov     r1, r5
9018    mov     r2, r4                      @ compare against self
9019    mov     r3, r5
9020    bl      __aeabi_dcmpeq              @ is arg == self?
9021    cmp     r0, #0                      @ zero == no
9022    moveq   r1, #0                      @ return zero for NaN
9023    beq     1f
9024
9025    mov     r0, r4                      @ recover arg
9026    mov     r1, r5
9027    bl      __aeabi_d2lz                @ convert double to long
9028
90291:
9030    add     sp, sp, #4
9031    ldmfd   sp!, {r4, r5, pc}
9032
9033/* continuation for OP_MUL_LONG */
9034
9035.LOP_MUL_LONG_finish:
9036    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9037    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9038    GOTO_OPCODE(ip)                     @ jump to next instruction
9039
9040/* continuation for OP_SHL_LONG */
9041
9042.LOP_SHL_LONG_finish:
9043    mov     r0, r0, asl r2              @  r0<- r0 << r2
9044    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9045    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9046    GOTO_OPCODE(ip)                     @ jump to next instruction
9047
9048/* continuation for OP_SHR_LONG */
9049
9050.LOP_SHR_LONG_finish:
9051    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9052    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9053    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9054    GOTO_OPCODE(ip)                     @ jump to next instruction
9055
9056/* continuation for OP_USHR_LONG */
9057
9058.LOP_USHR_LONG_finish:
9059    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9060    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9061    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9062    GOTO_OPCODE(ip)                     @ jump to next instruction
9063
9064/* continuation for OP_SHL_LONG_2ADDR */
9065
9066.LOP_SHL_LONG_2ADDR_finish:
9067    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9068    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9069    GOTO_OPCODE(ip)                     @ jump to next instruction
9070
9071/* continuation for OP_SHR_LONG_2ADDR */
9072
9073.LOP_SHR_LONG_2ADDR_finish:
9074    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9075    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9076    GOTO_OPCODE(ip)                     @ jump to next instruction
9077
9078/* continuation for OP_USHR_LONG_2ADDR */
9079
9080.LOP_USHR_LONG_2ADDR_finish:
9081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9082    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9083    GOTO_OPCODE(ip)                     @ jump to next instruction
9084
9085/* continuation for OP_IGET_VOLATILE */
9086
9087    /*
9088     * Currently:
9089     *  r0 holds resolved field
9090     *  r9 holds object
9091     */
9092.LOP_IGET_VOLATILE_finish:
9093    @bl      common_squeak0
9094    cmp     r9, #0                      @ check object for null
9095    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9096    beq     common_errNullObject        @ object was null
9097    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9098    SMP_DMB                            @ acquiring load
9099    mov     r2, rINST, lsr #8           @ r2<- A+
9100    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9101    and     r2, r2, #15                 @ r2<- A
9102    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9103    SET_VREG(r0, r2)                    @ fp[A]<- r0
9104    GOTO_OPCODE(ip)                     @ jump to next instruction
9105
9106/* continuation for OP_IPUT_VOLATILE */
9107
9108    /*
9109     * Currently:
9110     *  r0 holds resolved field
9111     *  r9 holds object
9112     */
9113.LOP_IPUT_VOLATILE_finish:
9114    @bl      common_squeak0
9115    mov     r1, rINST, lsr #8           @ r1<- A+
9116    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9117    and     r1, r1, #15                 @ r1<- A
9118    cmp     r9, #0                      @ check object for null
9119    GET_VREG(r0, r1)                    @ r0<- fp[A]
9120    beq     common_errNullObject        @ object was null
9121    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9122    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9123    SMP_DMB                            @ releasing store
9124    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9125    GOTO_OPCODE(ip)                     @ jump to next instruction
9126
9127/* continuation for OP_SGET_VOLATILE */
9128
9129    /*
9130     * Continuation if the field has not yet been resolved.
9131     *  r1: BBBB field ref
9132     */
9133.LOP_SGET_VOLATILE_resolve:
9134    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9135    EXPORT_PC()                         @ resolve() could throw, so export now
9136    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9137    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9138    cmp     r0, #0                      @ success?
9139    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9140    b       common_exceptionThrown      @ no, handle exception
9141
9142/* continuation for OP_SPUT_VOLATILE */
9143
9144    /*
9145     * Continuation if the field has not yet been resolved.
9146     *  r1: BBBB field ref
9147     */
9148.LOP_SPUT_VOLATILE_resolve:
9149    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9150    EXPORT_PC()                         @ resolve() could throw, so export now
9151    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9152    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9153    cmp     r0, #0                      @ success?
9154    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9155    b       common_exceptionThrown      @ no, handle exception
9156
9157/* continuation for OP_IGET_OBJECT_VOLATILE */
9158
9159    /*
9160     * Currently:
9161     *  r0 holds resolved field
9162     *  r9 holds object
9163     */
9164.LOP_IGET_OBJECT_VOLATILE_finish:
9165    @bl      common_squeak0
9166    cmp     r9, #0                      @ check object for null
9167    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9168    beq     common_errNullObject        @ object was null
9169    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9170    SMP_DMB                            @ acquiring load
9171    mov     r2, rINST, lsr #8           @ r2<- A+
9172    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9173    and     r2, r2, #15                 @ r2<- A
9174    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9175    SET_VREG(r0, r2)                    @ fp[A]<- r0
9176    GOTO_OPCODE(ip)                     @ jump to next instruction
9177
9178/* continuation for OP_IGET_WIDE_VOLATILE */
9179
9180    /*
9181     * Currently:
9182     *  r0 holds resolved field
9183     *  r9 holds object
9184     */
9185.LOP_IGET_WIDE_VOLATILE_finish:
9186    cmp     r9, #0                      @ check object for null
9187    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9188    beq     common_errNullObject        @ object was null
9189    .if     1
9190    add     r0, r9, r3                  @ r0<- address of field
9191    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9192    .else
9193    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9194    .endif
9195    mov     r2, rINST, lsr #8           @ r2<- A+
9196    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9197    and     r2, r2, #15                 @ r2<- A
9198    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9199    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9200    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9201    GOTO_OPCODE(ip)                     @ jump to next instruction
9202
9203/* continuation for OP_IPUT_WIDE_VOLATILE */
9204
9205    /*
9206     * Currently:
9207     *  r0 holds resolved field
9208     *  r9 holds object
9209     */
9210.LOP_IPUT_WIDE_VOLATILE_finish:
9211    mov     r2, rINST, lsr #8           @ r2<- A+
9212    cmp     r9, #0                      @ check object for null
9213    and     r2, r2, #15                 @ r2<- A
9214    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9215    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9216    beq     common_errNullObject        @ object was null
9217    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9218    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9219    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9220    .if     1
9221    add     r2, r9, r3                  @ r2<- target address
9222    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9223    .else
9224    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9225    .endif
9226    GOTO_OPCODE(r10)                    @ jump to next instruction
9227
9228/* continuation for OP_SGET_WIDE_VOLATILE */
9229
9230    /*
9231     * Continuation if the field has not yet been resolved.
9232     *  r1: BBBB field ref
9233     *
9234     * Returns StaticField pointer in r0.
9235     */
9236.LOP_SGET_WIDE_VOLATILE_resolve:
9237    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9238    EXPORT_PC()                         @ resolve() could throw, so export now
9239    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9240    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9241    cmp     r0, #0                      @ success?
9242    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9243    b       common_exceptionThrown      @ no, handle exception
9244
9245/* continuation for OP_SPUT_WIDE_VOLATILE */
9246
9247    /*
9248     * Continuation if the field has not yet been resolved.
9249     *  r1: BBBB field ref
9250     *  r9: &fp[AA]
9251     *
9252     * Returns StaticField pointer in r2.
9253     */
9254.LOP_SPUT_WIDE_VOLATILE_resolve:
9255    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9256    EXPORT_PC()                         @ resolve() could throw, so export now
9257    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9258    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9259    cmp     r0, #0                      @ success?
9260    mov     r2, r0                      @ copy to r2
9261    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9262    b       common_exceptionThrown      @ no, handle exception
9263
9264/* continuation for OP_EXECUTE_INLINE */
9265
9266    /*
9267     * Extract args, call function.
9268     *  r0 = #of args (0-4)
9269     *  r10 = call index
9270     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9271     *
9272     * Other ideas:
9273     * - Use a jump table from the main piece to jump directly into the
9274     *   AND/LDR pairs.  Costs a data load, saves a branch.
9275     * - Have five separate pieces that do the loading, so we can work the
9276     *   interleave a little better.  Increases code size.
9277     */
9278.LOP_EXECUTE_INLINE_continue:
9279    rsb     r0, r0, #4                  @ r0<- 4-r0
9280    FETCH(r9, 2)                        @ r9<- FEDC
9281    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9282    bl      common_abort                @ (skipped due to ARM prefetch)
92834:  and     ip, r9, #0xf000             @ isolate F
9284    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92853:  and     ip, r9, #0x0f00             @ isolate E
9286    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92872:  and     ip, r9, #0x00f0             @ isolate D
9288    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92891:  and     ip, r9, #0x000f             @ isolate C
9290    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92910:
9292    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9293    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9294    @ (not reached)
9295
9296.LOP_EXECUTE_INLINE_table:
9297    .word   gDvmInlineOpsTable
9298
9299/* continuation for OP_EXECUTE_INLINE_RANGE */
9300
9301    /*
9302     * Extract args, call function.
9303     *  r0 = #of args (0-4)
9304     *  r10 = call index
9305     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9306     */
9307.LOP_EXECUTE_INLINE_RANGE_continue:
9308    rsb     r0, r0, #4                  @ r0<- 4-r0
9309    FETCH(r9, 2)                        @ r9<- CCCC
9310    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9311    bl      common_abort                @ (skipped due to ARM prefetch)
93124:  add     ip, r9, #3                  @ base+3
9313    GET_VREG(r3, ip)                    @ r3<- vBase[3]
93143:  add     ip, r9, #2                  @ base+2
9315    GET_VREG(r2, ip)                    @ r2<- vBase[2]
93162:  add     ip, r9, #1                  @ base+1
9317    GET_VREG(r1, ip)                    @ r1<- vBase[1]
93181:  add     ip, r9, #0                  @ (nop)
9319    GET_VREG(r0, ip)                    @ r0<- vBase[0]
93200:
9321    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9322    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9323    @ (not reached)
9324
9325.LOP_EXECUTE_INLINE_RANGE_table:
9326    .word   gDvmInlineOpsTable
9327
9328/* continuation for OP_IPUT_OBJECT_VOLATILE */
9329
9330    /*
9331     * Currently:
9332     *  r0 holds resolved field
9333     *  r9 holds object
9334     */
9335.LOP_IPUT_OBJECT_VOLATILE_finish:
9336    @bl      common_squeak0
9337    mov     r1, rINST, lsr #8           @ r1<- A+
9338    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9339    and     r1, r1, #15                 @ r1<- A
9340    cmp     r9, #0                      @ check object for null
9341    GET_VREG(r0, r1)                    @ r0<- fp[A]
9342    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9343    beq     common_errNullObject        @ object was null
9344    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9346    SMP_DMB                            @ releasing store
9347    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
9348    cmp     r0, #0                      @ stored a null reference?
9349    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9350    GOTO_OPCODE(ip)                     @ jump to next instruction
9351
9352/* continuation for OP_SGET_OBJECT_VOLATILE */
9353
9354    /*
9355     * Continuation if the field has not yet been resolved.
9356     *  r1: BBBB field ref
9357     */
9358.LOP_SGET_OBJECT_VOLATILE_resolve:
9359    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9360    EXPORT_PC()                         @ resolve() could throw, so export now
9361    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9362    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9363    cmp     r0, #0                      @ success?
9364    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9365    b       common_exceptionThrown      @ no, handle exception
9366
9367/* continuation for OP_SPUT_OBJECT_VOLATILE */
9368.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9369    mov     r2, rINST, lsr #8           @ r2<- AA
9370    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9371    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9372    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9373    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9374    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9375    SMP_DMB                            @ releasing store
9376    str     r1, [r0, #offStaticField_value]  @ field<- vAA
9377    cmp     r1, #0                      @ stored a null object?
9378    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9379    GOTO_OPCODE(ip)                     @ jump to next instruction
9380
9381    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9382    .global dvmAsmSisterEnd
9383dvmAsmSisterEnd:
9384
9385/* File: armv5te/footer.S */
9386
9387/*
9388 * ===========================================================================
9389 *  Common subroutines and data
9390 * ===========================================================================
9391 */
9392
9393
9394
9395    .text
9396    .align  2
9397
9398#if defined(WITH_JIT)
9399#if defined(WITH_SELF_VERIFICATION)
9400    .global dvmJitToInterpPunt
9401dvmJitToInterpPunt:
9402    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9403    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9404    mov    r3, #0
9405    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9406    b      jitSVShadowRunEnd            @ doesn't return
9407
9408    .global dvmJitToInterpSingleStep
9409dvmJitToInterpSingleStep:
9410    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9411    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9412    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9413    b      jitSVShadowRunEnd            @ doesn't return
9414
9415    .global dvmJitToInterpNoChainNoProfile
9416dvmJitToInterpNoChainNoProfile:
9417    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9418    mov    r0,rPC                       @ pass our target PC
9419    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9420    mov    r3, #0                       @ 0 means !inJitCodeCache
9421    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9422    b      jitSVShadowRunEnd            @ doesn't return
9423
9424    .global dvmJitToInterpTraceSelectNoChain
9425dvmJitToInterpTraceSelectNoChain:
9426    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9427    mov    r0,rPC                       @ pass our target PC
9428    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9429    mov    r3, #0                       @ 0 means !inJitCodeCache
9430    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9431    b      jitSVShadowRunEnd            @ doesn't return
9432
9433    .global dvmJitToInterpTraceSelect
9434dvmJitToInterpTraceSelect:
9435    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9436    ldr    r0,[lr, #-1]                 @ pass our target PC
9437    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9438    mov    r3, #0                       @ 0 means !inJitCodeCache
9439    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9440    b      jitSVShadowRunEnd            @ doesn't return
9441
9442    .global dvmJitToInterpBackwardBranch
9443dvmJitToInterpBackwardBranch:
9444    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9445    ldr    r0,[lr, #-1]                 @ pass our target PC
9446    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9447    mov    r3, #0                       @ 0 means !inJitCodeCache
9448    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9449    b      jitSVShadowRunEnd            @ doesn't return
9450
9451    .global dvmJitToInterpNormal
9452dvmJitToInterpNormal:
9453    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9454    ldr    r0,[lr, #-1]                 @ pass our target PC
9455    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9456    mov    r3, #0                       @ 0 means !inJitCodeCache
9457    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9458    b      jitSVShadowRunEnd            @ doesn't return
9459
9460    .global dvmJitToInterpNoChain
9461dvmJitToInterpNoChain:
9462    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9463    mov    r0,rPC                       @ pass our target PC
9464    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9465    mov    r3, #0                       @ 0 means !inJitCodeCache
9466    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9467    b      jitSVShadowRunEnd            @ doesn't return
9468#else
9469/*
9470 * Return from the translation cache to the interpreter when the compiler is
9471 * having issues translating/executing a Dalvik instruction. We have to skip
9472 * the code cache lookup otherwise it is possible to indefinitely bouce
9473 * between the interpreter and the code cache if the instruction that fails
9474 * to be compiled happens to be at a trace start.
9475 */
9476    .global dvmJitToInterpPunt
9477dvmJitToInterpPunt:
9478    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9479    mov    rPC, r0
9480#if defined(WITH_JIT_TUNING)
9481    mov    r0,lr
9482    bl     dvmBumpPunt;
9483#endif
9484    EXPORT_PC()
9485    mov    r0, #0
9486    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9487    adrl   rIBASE, dvmAsmInstructionStart
9488    FETCH_INST()
9489    GET_INST_OPCODE(ip)
9490    GOTO_OPCODE(ip)
9491
9492/*
9493 * Return to the interpreter to handle a single instruction.
9494 * On entry:
9495 *    r0 <= PC
9496 *    r1 <= PC of resume instruction
9497 *    lr <= resume point in translation
9498 */
9499    .global dvmJitToInterpSingleStep
9500dvmJitToInterpSingleStep:
9501    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9502    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9503    mov    r1,#kInterpEntryInstr
9504    @ enum is 4 byte in aapcs-EABI
9505    str    r1, [rGLUE, #offGlue_entryPoint]
9506    mov    rPC,r0
9507    EXPORT_PC()
9508
9509    adrl   rIBASE, dvmAsmInstructionStart
9510    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9511    str    r2,[rGLUE,#offGlue_jitState]
9512    mov    r1,#1                  @ set changeInterp to bail to debug interp
9513    b      common_gotoBail
9514
9515/*
9516 * Return from the translation cache and immediately request
9517 * a translation for the exit target.  Commonly used for callees.
9518 */
9519    .global dvmJitToInterpTraceSelectNoChain
9520dvmJitToInterpTraceSelectNoChain:
9521#if defined(WITH_JIT_TUNING)
9522    bl     dvmBumpNoChain
9523#endif
9524    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9525    mov    r0,rPC
9526    bl     dvmJitGetCodeAddr        @ Is there a translation?
9527    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9528    mov    r1, rPC                  @ arg1 of translation may need this
9529    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9530    cmp    r0,#0                    @ !0 means translation exists
9531    bxne   r0                       @ continue native execution if so
9532    b      2f                       @ branch over to use the interpreter
9533
9534/*
9535 * Return from the translation cache and immediately request
9536 * a translation for the exit target.  Commonly used following
9537 * invokes.
9538 */
9539    .global dvmJitToInterpTraceSelect
9540dvmJitToInterpTraceSelect:
9541    ldr    rPC,[lr, #-1]           @ get our target PC
9542    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9543    add    rINST,lr,#-5            @ save start of chain branch
9544    add    rINST, #-4              @  .. which is 9 bytes back
9545    mov    r0,rPC
9546    bl     dvmJitGetCodeAddr       @ Is there a translation?
9547    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9548    cmp    r0,#0
9549    beq    2f
9550    mov    r1,rINST
9551    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9552    mov    r1, rPC                  @ arg1 of translation may need this
9553    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
9554    cmp    r0,#0                    @ successful chain?
9555    bxne   r0                       @ continue native execution
9556    b      toInterpreter            @ didn't chain - resume with interpreter
9557
9558/* No translation, so request one if profiling isn't disabled*/
95592:
9560    adrl   rIBASE, dvmAsmInstructionStart
9561    GET_JIT_PROF_TABLE(r0)
9562    FETCH_INST()
9563    cmp    r0, #0
9564    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
9565    bne    common_selectTrace
9566    GET_INST_OPCODE(ip)
9567    GOTO_OPCODE(ip)
9568
9569/*
9570 * Return from the translation cache to the interpreter.
9571 * The return was done with a BLX from thumb mode, and
9572 * the following 32-bit word contains the target rPC value.
9573 * Note that lr (r14) will have its low-order bit set to denote
9574 * its thumb-mode origin.
9575 *
9576 * We'll need to stash our lr origin away, recover the new
9577 * target and then check to see if there is a translation available
9578 * for our new target.  If so, we do a translation chain and
9579 * go back to native execution.  Otherwise, it's back to the
9580 * interpreter (after treating this entry as a potential
9581 * trace start).
9582 */
9583    .global dvmJitToInterpNormal
9584dvmJitToInterpNormal:
9585    ldr    rPC,[lr, #-1]           @ get our target PC
9586    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9587    add    rINST,lr,#-5            @ save start of chain branch
9588    add    rINST,#-4               @ .. which is 9 bytes back
9589#if defined(WITH_JIT_TUNING)
9590    bl     dvmBumpNormal
9591#endif
9592    mov    r0,rPC
9593    bl     dvmJitGetCodeAddr        @ Is there a translation?
9594    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9595    cmp    r0,#0
9596    beq    toInterpreter            @ go if not, otherwise do chain
9597    mov    r1,rINST
9598    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
9599    mov    r1, rPC                  @ arg1 of translation may need this
9600    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9601    cmp    r0,#0                    @ successful chain?
9602    bxne   r0                       @ continue native execution
9603    b      toInterpreter            @ didn't chain - resume with interpreter
9604
9605/*
9606 * Return from the translation cache to the interpreter to do method invocation.
9607 * Check if translation exists for the callee, but don't chain to it.
9608 */
9609    .global dvmJitToInterpNoChainNoProfile
9610dvmJitToInterpNoChainNoProfile:
9611#if defined(WITH_JIT_TUNING)
9612    bl     dvmBumpNoChain
9613#endif
9614    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9615    mov    r0,rPC
9616    bl     dvmJitGetCodeAddr        @ Is there a translation?
9617    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9618    mov    r1, rPC                  @ arg1 of translation may need this
9619    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9620    cmp    r0,#0
9621    bxne   r0                       @ continue native execution if so
9622    EXPORT_PC()
9623    adrl   rIBASE, dvmAsmInstructionStart
9624    FETCH_INST()
9625    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9626    GOTO_OPCODE(ip)                     @ jump to next instruction
9627
9628/*
9629 * Return from the translation cache to the interpreter to do method invocation.
9630 * Check if translation exists for the callee, but don't chain to it.
9631 */
9632    .global dvmJitToInterpNoChain
9633dvmJitToInterpNoChain:
9634#if defined(WITH_JIT_TUNING)
9635    bl     dvmBumpNoChain
9636#endif
9637    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9638    mov    r0,rPC
9639    bl     dvmJitGetCodeAddr        @ Is there a translation?
9640    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9641    mov    r1, rPC                  @ arg1 of translation may need this
9642    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9643    cmp    r0,#0
9644    bxne   r0                       @ continue native execution if so
9645#endif
9646
9647/*
9648 * No translation, restore interpreter regs and start interpreting.
9649 * rGLUE & rFP were preserved in the translated code, and rPC has
9650 * already been restored by the time we get here.  We'll need to set
9651 * up rIBASE & rINST, and load the address of the JitTable into r0.
9652 */
9653toInterpreter:
9654    EXPORT_PC()
9655    adrl   rIBASE, dvmAsmInstructionStart
9656    FETCH_INST()
9657    GET_JIT_PROF_TABLE(r0)
9658    @ NOTE: intended fallthrough
9659
9660/*
9661 * Common code to update potential trace start counter, and initiate
9662 * a trace-build if appropriate.  On entry, rPC should point to the
9663 * next instruction to execute, and rINST should be already loaded with
9664 * the next opcode word, and r0 holds a pointer to the jit profile
9665 * table (pJitProfTable).
9666 */
9667common_testUpdateProfile:
9668    cmp     r0,#0
9669    GET_INST_OPCODE(ip)
9670    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
9671
9672common_updateProfile:
9673    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
9674    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
9675    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
9676    GET_INST_OPCODE(ip)
9677    subs    r1,r1,#1           @ decrement counter
9678    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
9679    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
9680
9681/*
9682 * Here, we switch to the debug interpreter to request
9683 * trace selection.  First, though, check to see if there
9684 * is already a native translation in place (and, if so,
9685 * jump to it now).
9686 */
9687    GET_JIT_THRESHOLD(r1)
9688    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
9689    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
9690    EXPORT_PC()
9691    mov     r0,rPC
9692    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
9693    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9694    mov     r1, rPC                     @ arg1 of translation may need this
9695    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
9696    cmp     r0,#0
9697#if !defined(WITH_SELF_VERIFICATION)
9698    bxne    r0                          @ jump to the translation
9699    mov     r2,#kJitTSelectRequest      @ ask for trace selection
9700    @ fall-through to common_selectTrace
9701#else
9702    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
9703    beq     common_selectTrace
9704    /*
9705     * At this point, we have a target translation.  However, if
9706     * that translation is actually the interpret-only pseudo-translation
9707     * we want to treat it the same as no translation.
9708     */
9709    mov     r10, r0                     @ save target
9710    bl      dvmCompilerGetInterpretTemplate
9711    cmp     r0, r10                     @ special case?
9712    bne     jitSVShadowRunStart         @ set up self verification shadow space
9713    @ Need to clear the inJitCodeCache flag
9714    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
9715    mov    r3, #0                       @ 0 means not in the JIT code cache
9716    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9717    GET_INST_OPCODE(ip)
9718    GOTO_OPCODE(ip)
9719    /* no return */
9720#endif
9721
9722/*
9723 * On entry:
9724 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9725 */
9726common_selectTrace:
9727    str     r2,[rGLUE,#offGlue_jitState]
9728    mov     r2,#kInterpEntryInstr       @ normal entry reason
9729    str     r2,[rGLUE,#offGlue_entryPoint]
9730    mov     r1,#1                       @ set changeInterp
9731    b       common_gotoBail
9732
9733#if defined(WITH_SELF_VERIFICATION)
9734/*
9735 * Save PC and registers to shadow memory for self verification mode
9736 * before jumping to native translation.
9737 * On entry:
9738 *    rPC, rFP, rGLUE: the values that they should contain
9739 *    r10: the address of the target translation.
9740 */
9741jitSVShadowRunStart:
9742    mov     r0,rPC                      @ r0<- program counter
9743    mov     r1,rFP                      @ r1<- frame pointer
9744    mov     r2,rGLUE                    @ r2<- InterpState pointer
9745    mov     r3,r10                      @ r3<- target translation
9746    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9747    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9748    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9749    bx      r10                         @ jump to the translation
9750
9751/*
9752 * Restore PC, registers, and interpState to original values
9753 * before jumping back to the interpreter.
9754 */
9755jitSVShadowRunEnd:
9756    mov    r1,rFP                        @ pass ending fp
9757    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9758    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9759    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9760    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9761    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9762    cmp    r1,#0                         @ check for punt condition
9763    beq    1f
9764    mov    r2,#kJitSelfVerification      @ ask for self verification
9765    str    r2,[rGLUE,#offGlue_jitState]
9766    mov    r2,#kInterpEntryInstr         @ normal entry reason
9767    str    r2,[rGLUE,#offGlue_entryPoint]
9768    mov    r1,#1                         @ set changeInterp
9769    b      common_gotoBail
9770
97711:                                       @ exit to interpreter without check
9772    EXPORT_PC()
9773    adrl   rIBASE, dvmAsmInstructionStart
9774    FETCH_INST()
9775    GET_INST_OPCODE(ip)
9776    GOTO_OPCODE(ip)
9777#endif
9778
9779#endif
9780
9781/*
9782 * Common code when a backward branch is taken.
9783 *
9784 * TODO: we could avoid a branch by just setting r0 and falling through
9785 * into the common_periodicChecks code, and having a test on r0 at the
9786 * end determine if we should return to the caller or update & branch to
9787 * the next instr.
9788 *
9789 * On entry:
9790 *  r9 is PC adjustment *in bytes*
9791 */
9792common_backwardBranch:
9793    mov     r0, #kInterpEntryInstr
9794    bl      common_periodicChecks
9795#if defined(WITH_JIT)
9796    GET_JIT_PROF_TABLE(r0)
9797    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9798    cmp     r0,#0
9799    bne     common_updateProfile
9800    GET_INST_OPCODE(ip)
9801    GOTO_OPCODE(ip)
9802#else
9803    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9804    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9805    GOTO_OPCODE(ip)                     @ jump to next instruction
9806#endif
9807
9808
9809/*
9810 * Need to see if the thread needs to be suspended or debugger/profiler
9811 * activity has begun.  If so, we suspend the thread or side-exit to
9812 * the debug interpreter as appropriate.
9813 *
9814 * The common case is no activity on any of these, so we want to figure
9815 * that out quickly.  If something is up, we can then sort out what.
9816 *
9817 * We want to be fast if the VM was built without debugger or profiler
9818 * support, but we also need to recognize that the system is usually
9819 * shipped with both of these enabled.
9820 *
9821 * TODO: reduce this so we're just checking a single location.
9822 *
9823 * On entry:
9824 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9825 *  r9 is trampoline PC adjustment *in bytes*
9826 */
9827common_periodicChecks:
9828    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9829
9830    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9831    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9832
9833    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9834
9835    cmp     r1, #0                      @ debugger enabled?
9836    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9837    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9838    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9839    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9840
9841    bxeq    lr                          @ all zero, return
9842
9843    /*
9844     * One or more interesting events have happened.  Figure out what.
9845     *
9846     * If debugging or profiling are compiled in, we need to disambiguate.
9847     *
9848     * r0 still holds the reentry type.
9849     */
9850    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9851    cmp     ip, #0                      @ want suspend?
9852    beq     1f                          @ no, must be debugger/profiler
9853
9854    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9855#if defined(WITH_JIT)
9856    /*
9857     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9858     * doubles as the Jit's on/off switch.
9859     */
9860    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9861    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9862    ldr     r3, [r3] @ r3 <- pJitProfTable
9863    EXPORT_PC()                         @ need for precise GC
9864    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9865#else
9866    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9867    EXPORT_PC()                         @ need for precise GC
9868#endif
9869    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9870    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9871
9872    /*
9873     * Reload the debugger/profiler enable flags.  We're checking to see
9874     * if either of these got set while we were suspended.
9875     *
9876     * We can't really avoid the #ifdefs here, because the fields don't
9877     * exist when the feature is disabled.
9878     */
9879    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9880    cmp     r1, #0                      @ debugger enabled?
9881    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9882    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9883    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9884
9885    orrs    r1, r1, r2
9886    beq     2f
9887
98881:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9889    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9890    add     rPC, rPC, r9                @ update rPC
9891    mov     r1, #1                      @ "want switch" = true
9892    b       common_gotoBail             @ side exit
9893
98942:
9895    bx      lr                          @ nothing to do, return
9896
9897
9898/*
9899 * The equivalent of "goto bail", this calls through the "bail handler".
9900 *
9901 * State registers will be saved to the "glue" area before bailing.
9902 *
9903 * On entry:
9904 *  r1 is "bool changeInterp", indicating if we want to switch to the
9905 *     other interpreter or just bail all the way out
9906 */
9907common_gotoBail:
9908    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9909    mov     r0, rGLUE                   @ r0<- glue ptr
9910    b       dvmMterpStdBail             @ call(glue, changeInterp)
9911
9912    @add     r1, r1, #1                  @ using (boolean+1)
9913    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9914    @bl      _longjmp                    @ does not return
9915    @bl      common_abort
9916
9917
9918/*
9919 * Common code for method invocation with range.
9920 *
9921 * On entry:
9922 *  r0 is "Method* methodToCall", the method we're trying to call
9923 */
9924common_invokeMethodRange:
9925.LinvokeNewRange:
9926    @ prepare to copy args to "outs" area of current frame
9927    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9928    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9929    beq     .LinvokeArgsDone            @ if no args, skip the rest
9930    FETCH(r1, 2)                        @ r1<- CCCC
9931
9932    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9933    @ (very few methods have > 10 args; could unroll for common cases)
9934    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9935    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9936    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
99371:  ldr     r1, [r3], #4                @ val = *fp++
9938    subs    r2, r2, #1                  @ count--
9939    str     r1, [r10], #4               @ *outs++ = val
9940    bne     1b                          @ ...while count != 0
9941    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9942    b       .LinvokeArgsDone
9943
9944/*
9945 * Common code for method invocation without range.
9946 *
9947 * On entry:
9948 *  r0 is "Method* methodToCall", the method we're trying to call
9949 */
9950common_invokeMethodNoRange:
9951.LinvokeNewNoRange:
9952    @ prepare to copy args to "outs" area of current frame
9953    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9954    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9955    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9956    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9957    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9958    beq     .LinvokeArgsDone
9959
9960    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9961.LinvokeNonRange:
9962    rsb     r2, r2, #5                  @ r2<- 5-r2
9963    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9964    bl      common_abort                @ (skipped due to ARM prefetch)
99655:  and     ip, rINST, #0x0f00          @ isolate A
9966    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9967    mov     r0, r0                      @ nop
9968    str     r2, [r10, #-4]!             @ *--outs = vA
99694:  and     ip, r1, #0xf000             @ isolate G
9970    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9971    mov     r0, r0                      @ nop
9972    str     r2, [r10, #-4]!             @ *--outs = vG
99733:  and     ip, r1, #0x0f00             @ isolate F
9974    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9975    mov     r0, r0                      @ nop
9976    str     r2, [r10, #-4]!             @ *--outs = vF
99772:  and     ip, r1, #0x00f0             @ isolate E
9978    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9979    mov     r0, r0                      @ nop
9980    str     r2, [r10, #-4]!             @ *--outs = vE
99811:  and     ip, r1, #0x000f             @ isolate D
9982    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9983    mov     r0, r0                      @ nop
9984    str     r2, [r10, #-4]!             @ *--outs = vD
99850:  @ fall through to .LinvokeArgsDone
9986
9987.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9988    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
9989    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
9990    @ find space for the new stack frame, check for overflow
9991    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
9992    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
9993    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
9994@    bl      common_dumpRegs
9995    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
9996    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
9997    cmp     r3, r9                      @ bottom < interpStackEnd?
9998    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
9999    blo     .LstackOverflow             @ yes, this frame will overflow stack
10000
10001    @ set up newSaveArea
10002#ifdef EASY_GDB
10003    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
10004    str     ip, [r10, #offStackSaveArea_prevSave]
10005#endif
10006    str     rFP, [r10, #offStackSaveArea_prevFrame]
10007    str     rPC, [r10, #offStackSaveArea_savedPc]
10008#if defined(WITH_JIT)
10009    mov     r9, #0
10010    str     r9, [r10, #offStackSaveArea_returnAddr]
10011#endif
10012    str     r0, [r10, #offStackSaveArea_method]
10013    tst     r3, #ACC_NATIVE
10014    bne     .LinvokeNative
10015
10016    /*
10017    stmfd   sp!, {r0-r3}
10018    bl      common_printNewline
10019    mov     r0, rFP
10020    mov     r1, #0
10021    bl      dvmDumpFp
10022    ldmfd   sp!, {r0-r3}
10023    stmfd   sp!, {r0-r3}
10024    mov     r0, r1
10025    mov     r1, r10
10026    bl      dvmDumpFp
10027    bl      common_printNewline
10028    ldmfd   sp!, {r0-r3}
10029    */
10030
10031    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10032    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10033    mov     rPC, r2                         @ publish new rPC
10034    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10035
10036    @ Update "glue" values for the new method
10037    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10038    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10039    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10040#if defined(WITH_JIT)
10041    GET_JIT_PROF_TABLE(r0)
10042    mov     rFP, r1                         @ fp = newFp
10043    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10044    mov     rINST, r9                       @ publish new rINST
10045    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10046    cmp     r0,#0
10047    bne     common_updateProfile
10048    GOTO_OPCODE(ip)                         @ jump to next instruction
10049#else
10050    mov     rFP, r1                         @ fp = newFp
10051    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10052    mov     rINST, r9                       @ publish new rINST
10053    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10054    GOTO_OPCODE(ip)                         @ jump to next instruction
10055#endif
10056
10057.LinvokeNative:
10058    @ Prep for the native call
10059    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10060    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10061    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10062    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10063    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10064    mov     r9, r3                      @ r9<- glue->self (preserve)
10065
10066    mov     r2, r0                      @ r2<- methodToCall
10067    mov     r0, r1                      @ r0<- newFp (points to args)
10068    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10069
10070#ifdef ASSIST_DEBUGGER
10071    /* insert fake function header to help gdb find the stack frame */
10072    b       .Lskip
10073    .type   dalvik_mterp, %function
10074dalvik_mterp:
10075    .fnstart
10076    MTERP_ENTRY1
10077    MTERP_ENTRY2
10078.Lskip:
10079#endif
10080
10081    @mov     lr, pc                      @ set return addr
10082    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10083    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10084
10085#if defined(WITH_JIT)
10086    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10087#endif
10088
10089    @ native return; r9=self, r10=newSaveArea
10090    @ equivalent to dvmPopJniLocals
10091    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10092    ldr     r1, [r9, #offThread_exception] @ check for exception
10093#if defined(WITH_JIT)
10094    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10095#endif
10096    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10097    cmp     r1, #0                      @ null?
10098    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10099#if defined(WITH_JIT)
10100    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10101#endif
10102    bne     common_exceptionThrown      @ no, handle exception
10103
10104    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10105    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10106    GOTO_OPCODE(ip)                     @ jump to next instruction
10107
10108.LstackOverflow:    @ r0=methodToCall
10109    mov     r1, r0                      @ r1<- methodToCall
10110    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10111    bl      dvmHandleStackOverflow
10112    b       common_exceptionThrown
10113#ifdef ASSIST_DEBUGGER
10114    .fnend
10115#endif
10116
10117
10118    /*
10119     * Common code for method invocation, calling through "glue code".
10120     *
10121     * TODO: now that we have range and non-range invoke handlers, this
10122     *       needs to be split into two.  Maybe just create entry points
10123     *       that set r9 and jump here?
10124     *
10125     * On entry:
10126     *  r0 is "Method* methodToCall", the method we're trying to call
10127     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10128     */
10129     .if    0
10130.LinvokeOld:
10131    sub     sp, sp, #8                  @ space for args + pad
10132    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10133    mov     r2, r0                      @ A2<- methodToCall
10134    mov     r0, rGLUE                   @ A0<- glue
10135    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10136    mov     r1, r9                      @ A1<- methodCallRange
10137    mov     r3, rINST, lsr #8           @ A3<- AA
10138    str     ip, [sp, #0]                @ A4<- ip
10139    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10140    add     sp, sp, #8                  @ remove arg area
10141    b       common_resumeAfterGlueCall  @ continue to next instruction
10142    .endif
10143
10144
10145
10146/*
10147 * Common code for handling a return instruction.
10148 *
10149 * This does not return.
10150 */
10151common_returnFromMethod:
10152.LreturnNew:
10153    mov     r0, #kInterpEntryReturn
10154    mov     r9, #0
10155    bl      common_periodicChecks
10156
10157    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10158    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10159    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10160    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10161                                        @ r2<- method we're returning to
10162    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10163    cmp     r2, #0                      @ is this a break frame?
10164    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10165    mov     r1, #0                      @ "want switch" = false
10166    beq     common_gotoBail             @ break frame, bail out completely
10167
10168    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10169    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10170    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10171    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10172#if defined(WITH_JIT)
10173    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10174    mov     rPC, r9                     @ publish new rPC
10175    str     r1, [rGLUE, #offGlue_methodClassDex]
10176    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10177    cmp     r10, #0                      @ caller is compiled code
10178    blxne   r10
10179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10180    GOTO_OPCODE(ip)                     @ jump to next instruction
10181#else
10182    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10183    mov     rPC, r9                     @ publish new rPC
10184    str     r1, [rGLUE, #offGlue_methodClassDex]
10185    GOTO_OPCODE(ip)                     @ jump to next instruction
10186#endif
10187
10188    /*
10189     * Return handling, calls through "glue code".
10190     */
10191     .if    0
10192.LreturnOld:
10193    SAVE_PC_FP_TO_GLUE()                @ export state
10194    mov     r0, rGLUE                   @ arg to function
10195    bl      dvmMterp_returnFromMethod
10196    b       common_resumeAfterGlueCall
10197    .endif
10198
10199
10200/*
10201 * Somebody has thrown an exception.  Handle it.
10202 *
10203 * If the exception processing code returns to us (instead of falling
10204 * out of the interpreter), continue with whatever the next instruction
10205 * now happens to be.
10206 *
10207 * This does not return.
10208 */
10209     .global dvmMterpCommonExceptionThrown
10210dvmMterpCommonExceptionThrown:
10211common_exceptionThrown:
10212.LexceptionNew:
10213    mov     r0, #kInterpEntryThrow
10214    mov     r9, #0
10215    bl      common_periodicChecks
10216
10217    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10218    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10219    mov     r1, r10                     @ r1<- self
10220    mov     r0, r9                      @ r0<- exception
10221    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10222    mov     r3, #0                      @ r3<- NULL
10223    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10224
10225    /* set up args and a local for "&fp" */
10226    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10227    str     rFP, [sp, #-4]!             @ *--sp = fp
10228    mov     ip, sp                      @ ip<- &fp
10229    mov     r3, #0                      @ r3<- false
10230    str     ip, [sp, #-4]!              @ *--sp = &fp
10231    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10232    mov     r0, r10                     @ r0<- self
10233    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10234    mov     r2, r9                      @ r2<- exception
10235    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10236    mov     r1, r1, asr #1              @ r1<- offset in code units
10237
10238    /* call, r0 gets catchRelPc (a code-unit offset) */
10239    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10240
10241    /* fix earlier stack overflow if necessary; may trash rFP */
10242    ldrb    r1, [r10, #offThread_stackOverflowed]
10243    cmp     r1, #0                      @ did we overflow earlier?
10244    beq     1f                          @ no, skip ahead
10245    mov     rFP, r0                     @ save relPc result in rFP
10246    mov     r0, r10                     @ r0<- self
10247    mov     r1, r9                      @ r1<- exception
10248    bl      dvmCleanupStackOverflow     @ call(self)
10249    mov     r0, rFP                     @ restore result
102501:
10251
10252    /* update frame pointer and check result from dvmFindCatchBlock */
10253    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10254    cmp     r0, #0                      @ is catchRelPc < 0?
10255    add     sp, sp, #8                  @ restore stack
10256    bmi     .LnotCaughtLocally
10257
10258    /* adjust locals to match self->curFrame and updated PC */
10259    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10260    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10261    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10262    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10263    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10264    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10265    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10266    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10267
10268    /* release the tracked alloc on the exception */
10269    mov     r0, r9                      @ r0<- exception
10270    mov     r1, r10                     @ r1<- self
10271    bl      dvmReleaseTrackedAlloc      @ release the exception
10272
10273    /* restore the exception if the handler wants it */
10274    FETCH_INST()                        @ load rINST from rPC
10275    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10276    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10277    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10278    GOTO_OPCODE(ip)                     @ jump to next instruction
10279
10280.LnotCaughtLocally: @ r9=exception, r10=self
10281    /* fix stack overflow if necessary */
10282    ldrb    r1, [r10, #offThread_stackOverflowed]
10283    cmp     r1, #0                      @ did we overflow earlier?
10284    movne   r0, r10                     @ if yes: r0<- self
10285    movne   r1, r9                      @ if yes: r1<- exception
10286    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10287
10288    @ may want to show "not caught locally" debug messages here
10289#if DVM_SHOW_EXCEPTION >= 2
10290    /* call __android_log_print(prio, tag, format, ...) */
10291    /* "Exception %s from %s:%d not caught locally" */
10292    @ dvmLineNumFromPC(method, pc - method->insns)
10293    ldr     r0, [rGLUE, #offGlue_method]
10294    ldr     r1, [r0, #offMethod_insns]
10295    sub     r1, rPC, r1
10296    asr     r1, r1, #1
10297    bl      dvmLineNumFromPC
10298    str     r0, [sp, #-4]!
10299    @ dvmGetMethodSourceFile(method)
10300    ldr     r0, [rGLUE, #offGlue_method]
10301    bl      dvmGetMethodSourceFile
10302    str     r0, [sp, #-4]!
10303    @ exception->clazz->descriptor
10304    ldr     r3, [r9, #offObject_clazz]
10305    ldr     r3, [r3, #offClassObject_descriptor]
10306    @
10307    ldr     r2, strExceptionNotCaughtLocally
10308    ldr     r1, strLogTag
10309    mov     r0, #3                      @ LOG_DEBUG
10310    bl      __android_log_print
10311#endif
10312    str     r9, [r10, #offThread_exception] @ restore exception
10313    mov     r0, r9                      @ r0<- exception
10314    mov     r1, r10                     @ r1<- self
10315    bl      dvmReleaseTrackedAlloc      @ release the exception
10316    mov     r1, #0                      @ "want switch" = false
10317    b       common_gotoBail             @ bail out
10318
10319
10320    /*
10321     * Exception handling, calls through "glue code".
10322     */
10323    .if     0
10324.LexceptionOld:
10325    SAVE_PC_FP_TO_GLUE()                @ export state
10326    mov     r0, rGLUE                   @ arg to function
10327    bl      dvmMterp_exceptionThrown
10328    b       common_resumeAfterGlueCall
10329    .endif
10330
10331
10332/*
10333 * After returning from a "glued" function, pull out the updated
10334 * values and start executing at the next instruction.
10335 */
10336common_resumeAfterGlueCall:
10337    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10338    FETCH_INST()                        @ load rINST from rPC
10339    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10340    GOTO_OPCODE(ip)                     @ jump to next instruction
10341
10342/*
10343 * Invalid array index.
10344 */
10345common_errArrayIndex:
10346    EXPORT_PC()
10347    ldr     r0, strArrayIndexException
10348    mov     r1, #0
10349    bl      dvmThrowException
10350    b       common_exceptionThrown
10351
10352/*
10353 * Invalid array value.
10354 */
10355common_errArrayStore:
10356    EXPORT_PC()
10357    ldr     r0, strArrayStoreException
10358    mov     r1, #0
10359    bl      dvmThrowException
10360    b       common_exceptionThrown
10361
10362/*
10363 * Integer divide or mod by zero.
10364 */
10365common_errDivideByZero:
10366    EXPORT_PC()
10367    ldr     r0, strArithmeticException
10368    ldr     r1, strDivideByZero
10369    bl      dvmThrowException
10370    b       common_exceptionThrown
10371
10372/*
10373 * Attempt to allocate an array with a negative size.
10374 */
10375common_errNegativeArraySize:
10376    EXPORT_PC()
10377    ldr     r0, strNegativeArraySizeException
10378    mov     r1, #0
10379    bl      dvmThrowException
10380    b       common_exceptionThrown
10381
10382/*
10383 * Invocation of a non-existent method.
10384 */
10385common_errNoSuchMethod:
10386    EXPORT_PC()
10387    ldr     r0, strNoSuchMethodError
10388    mov     r1, #0
10389    bl      dvmThrowException
10390    b       common_exceptionThrown
10391
10392/*
10393 * We encountered a null object when we weren't expecting one.  We
10394 * export the PC, throw a NullPointerException, and goto the exception
10395 * processing code.
10396 */
10397common_errNullObject:
10398    EXPORT_PC()
10399    ldr     r0, strNullPointerException
10400    mov     r1, #0
10401    bl      dvmThrowException
10402    b       common_exceptionThrown
10403
10404/*
10405 * For debugging, cause an immediate fault.  The source address will
10406 * be in lr (use a bl instruction to jump here).
10407 */
10408common_abort:
10409    ldr     pc, .LdeadFood
10410.LdeadFood:
10411    .word   0xdeadf00d
10412
10413/*
10414 * Spit out a "we were here", preserving all registers.  (The attempt
10415 * to save ip won't work, but we need to save an even number of
10416 * registers for EABI 64-bit stack alignment.)
10417 */
10418    .macro  SQUEAK num
10419common_squeak\num:
10420    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10421    ldr     r0, strSqueak
10422    mov     r1, #\num
10423    bl      printf
10424    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10425    bx      lr
10426    .endm
10427
10428    SQUEAK  0
10429    SQUEAK  1
10430    SQUEAK  2
10431    SQUEAK  3
10432    SQUEAK  4
10433    SQUEAK  5
10434
10435/*
10436 * Spit out the number in r0, preserving registers.
10437 */
10438common_printNum:
10439    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10440    mov     r1, r0
10441    ldr     r0, strSqueak
10442    bl      printf
10443    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10444    bx      lr
10445
10446/*
10447 * Print a newline, preserving registers.
10448 */
10449common_printNewline:
10450    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10451    ldr     r0, strNewline
10452    bl      printf
10453    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10454    bx      lr
10455
10456    /*
10457     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10458     */
10459common_printHex:
10460    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10461    mov     r1, r0
10462    ldr     r0, strPrintHex
10463    bl      printf
10464    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10465    bx      lr
10466
10467/*
10468 * Print the 64-bit quantity in r0-r1, preserving registers.
10469 */
10470common_printLong:
10471    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10472    mov     r3, r1
10473    mov     r2, r0
10474    ldr     r0, strPrintLong
10475    bl      printf
10476    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10477    bx      lr
10478
10479/*
10480 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10481 */
10482common_printMethod:
10483    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10484    bl      dvmMterpPrintMethod
10485    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10486    bx      lr
10487
10488/*
10489 * Call a C helper function that dumps regs and possibly some
10490 * additional info.  Requires the C function to be compiled in.
10491 */
10492    .if     0
10493common_dumpRegs:
10494    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10495    bl      dvmMterpDumpArmRegs
10496    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10497    bx      lr
10498    .endif
10499
10500#if 0
10501/*
10502 * Experiment on VFP mode.
10503 *
10504 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10505 *
10506 * Updates the bits specified by "mask", setting them to the values in "val".
10507 */
10508setFPSCR:
10509    and     r0, r0, r1                  @ make sure no stray bits are set
10510    fmrx    r2, fpscr                   @ get VFP reg
10511    mvn     r1, r1                      @ bit-invert mask
10512    and     r2, r2, r1                  @ clear masked bits
10513    orr     r2, r2, r0                  @ set specified bits
10514    fmxr    fpscr, r2                   @ set VFP reg
10515    mov     r0, r2                      @ return new value
10516    bx      lr
10517
10518    .align  2
10519    .global dvmConfigureFP
10520    .type   dvmConfigureFP, %function
10521dvmConfigureFP:
10522    stmfd   sp!, {ip, lr}
10523    /* 0x03000000 sets DN/FZ */
10524    /* 0x00009f00 clears the six exception enable flags */
10525    bl      common_squeak0
10526    mov     r0, #0x03000000             @ r0<- 0x03000000
10527    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10528    bl      setFPSCR
10529    ldmfd   sp!, {ip, pc}
10530#endif
10531
10532
10533/*
10534 * String references, must be close to the code that uses them.
10535 */
10536    .align  2
10537strArithmeticException:
10538    .word   .LstrArithmeticException
10539strArrayIndexException:
10540    .word   .LstrArrayIndexException
10541strArrayStoreException:
10542    .word   .LstrArrayStoreException
10543strDivideByZero:
10544    .word   .LstrDivideByZero
10545strNegativeArraySizeException:
10546    .word   .LstrNegativeArraySizeException
10547strNoSuchMethodError:
10548    .word   .LstrNoSuchMethodError
10549strNullPointerException:
10550    .word   .LstrNullPointerException
10551
10552strLogTag:
10553    .word   .LstrLogTag
10554strExceptionNotCaughtLocally:
10555    .word   .LstrExceptionNotCaughtLocally
10556
10557strNewline:
10558    .word   .LstrNewline
10559strSqueak:
10560    .word   .LstrSqueak
10561strPrintHex:
10562    .word   .LstrPrintHex
10563strPrintLong:
10564    .word   .LstrPrintLong
10565
10566/*
10567 * Zero-terminated ASCII string data.
10568 *
10569 * On ARM we have two choices: do like gcc does, and LDR from a .word
10570 * with the address, or use an ADR pseudo-op to get the address
10571 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10572 * PC-relative addressing mode and hence has a limited range, which
10573 * makes it not work well with mergeable string sections.
10574 */
10575    .section .rodata.str1.4,"aMS",%progbits,1
10576
10577.LstrBadEntryPoint:
10578    .asciz  "Bad entry point %d\n"
10579.LstrArithmeticException:
10580    .asciz  "Ljava/lang/ArithmeticException;"
10581.LstrArrayIndexException:
10582    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10583.LstrArrayStoreException:
10584    .asciz  "Ljava/lang/ArrayStoreException;"
10585.LstrClassCastException:
10586    .asciz  "Ljava/lang/ClassCastException;"
10587.LstrDivideByZero:
10588    .asciz  "divide by zero"
10589.LstrFilledNewArrayNotImpl:
10590    .asciz  "filled-new-array only implemented for objects and 'int'"
10591.LstrInternalError:
10592    .asciz  "Ljava/lang/InternalError;"
10593.LstrInstantiationError:
10594    .asciz  "Ljava/lang/InstantiationError;"
10595.LstrNegativeArraySizeException:
10596    .asciz  "Ljava/lang/NegativeArraySizeException;"
10597.LstrNoSuchMethodError:
10598    .asciz  "Ljava/lang/NoSuchMethodError;"
10599.LstrNullPointerException:
10600    .asciz  "Ljava/lang/NullPointerException;"
10601
10602.LstrLogTag:
10603    .asciz  "mterp"
10604.LstrExceptionNotCaughtLocally:
10605    .asciz  "Exception %s from %s:%d not caught locally\n"
10606
10607.LstrNewline:
10608    .asciz  "\n"
10609.LstrSqueak:
10610    .asciz  "<%d>"
10611.LstrPrintHex:
10612    .asciz  "<0x%x>"
10613.LstrPrintLong:
10614    .asciz  "<%lld>"
10615
10616