InterpAsm-armv5te-vfp.S revision 291758c5c4902900c6f86794ba8ab9cad9b26197
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(r1, r2)                    @ r1<- vBB (array object)
2268    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2269    cmp     r1, #0                      @ null array object?
2270    GET_VREG(r9, r9)                    @ r9<- vAA
2271    beq     common_errNullObject        @ yes, bail
2272    ldr     r3, [r1, #offArrayObject_length]    @ r3<- arrayObj->length
2273    add     r10, r1, 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     r2, [rGLUE, #offGlue_method]    @ r2<- current method
3048    EXPORT_PC()                         @ resolve() could throw, so export now
3049    ldr     r0, [r2, #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_RETURN_VOID_BARRIER: /* 0xf1 */
7456/* File: armv5te/OP_RETURN_VOID_BARRIER.S */
7457    SMP_DMB                             @ TODO: want "DMB ST"
7458    b       common_returnFromMethod
7459
7460/* ------------------------------ */
7461    .balign 64
7462.L_OP_IGET_QUICK: /* 0xf2 */
7463/* File: armv5te/OP_IGET_QUICK.S */
7464    /* For: iget-quick, iget-object-quick */
7465    /* op vA, vB, offset@CCCC */
7466    mov     r2, rINST, lsr #12          @ r2<- B
7467    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7468    FETCH(r1, 1)                        @ r1<- field byte offset
7469    cmp     r3, #0                      @ check object for null
7470    mov     r2, rINST, lsr #8           @ r2<- A(+)
7471    beq     common_errNullObject        @ object was null
7472    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7473    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7474    and     r2, r2, #15
7475    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7476    SET_VREG(r0, r2)                    @ fp[A]<- r0
7477    GOTO_OPCODE(ip)                     @ jump to next instruction
7478
7479/* ------------------------------ */
7480    .balign 64
7481.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7482/* File: armv5te/OP_IGET_WIDE_QUICK.S */
7483    /* iget-wide-quick vA, vB, offset@CCCC */
7484    mov     r2, rINST, lsr #12          @ r2<- B
7485    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7486    FETCH(ip, 1)                        @ ip<- field byte offset
7487    cmp     r3, #0                      @ check object for null
7488    mov     r2, rINST, lsr #8           @ r2<- A(+)
7489    beq     common_errNullObject        @ object was null
7490    ldrd    r0, [r3, ip]                @ r0<- obj.field (64 bits, aligned)
7491    and     r2, r2, #15
7492    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7493    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7494    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7495    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7496    GOTO_OPCODE(ip)                     @ jump to next instruction
7497
7498/* ------------------------------ */
7499    .balign 64
7500.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7501/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7502/* File: armv5te/OP_IGET_QUICK.S */
7503    /* For: iget-quick, iget-object-quick */
7504    /* op vA, vB, offset@CCCC */
7505    mov     r2, rINST, lsr #12          @ r2<- B
7506    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7507    FETCH(r1, 1)                        @ r1<- field byte offset
7508    cmp     r3, #0                      @ check object for null
7509    mov     r2, rINST, lsr #8           @ r2<- A(+)
7510    beq     common_errNullObject        @ object was null
7511    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7512    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7513    and     r2, r2, #15
7514    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7515    SET_VREG(r0, r2)                    @ fp[A]<- r0
7516    GOTO_OPCODE(ip)                     @ jump to next instruction
7517
7518
7519/* ------------------------------ */
7520    .balign 64
7521.L_OP_IPUT_QUICK: /* 0xf5 */
7522/* File: armv5te/OP_IPUT_QUICK.S */
7523    /* For: iput-quick */
7524    /* op vA, vB, offset@CCCC */
7525    mov     r2, rINST, lsr #12          @ r2<- B
7526    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7527    FETCH(r1, 1)                        @ r1<- field byte offset
7528    cmp     r3, #0                      @ check object for null
7529    mov     r2, rINST, lsr #8           @ r2<- A(+)
7530    beq     common_errNullObject        @ object was null
7531    and     r2, r2, #15
7532    GET_VREG(r0, r2)                    @ r0<- fp[A]
7533    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7534    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7536    GOTO_OPCODE(ip)                     @ jump to next instruction
7537
7538/* ------------------------------ */
7539    .balign 64
7540.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7541/* File: armv5te/OP_IPUT_WIDE_QUICK.S */
7542    /* iput-wide-quick vA, vB, offset@CCCC */
7543    mov     r0, rINST, lsr #8           @ r0<- A(+)
7544    mov     r1, rINST, lsr #12          @ r1<- B
7545    and     r0, r0, #15
7546    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7547    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7548    cmp     r2, #0                      @ check object for null
7549    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7550    beq     common_errNullObject        @ object was null
7551    FETCH(r3, 1)                        @ r3<- field byte offset
7552    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7553    strd    r0, [r2, r3]                @ obj.field (64 bits, aligned)<- r0/r1
7554    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7555    GOTO_OPCODE(ip)                     @ jump to next instruction
7556
7557/* ------------------------------ */
7558    .balign 64
7559.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7560/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7561    /* For: iput-object-quick */
7562    /* op vA, vB, offset@CCCC */
7563    mov     r2, rINST, lsr #12          @ r2<- B
7564    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7565    FETCH(r1, 1)                        @ r1<- field byte offset
7566    cmp     r3, #0                      @ check object for null
7567    mov     r2, rINST, lsr #8           @ r2<- A(+)
7568    beq     common_errNullObject        @ object was null
7569    and     r2, r2, #15
7570    GET_VREG(r0, r2)                    @ r0<- fp[A]
7571    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7572    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7573    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7574    cmp     r0, #0
7575    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card on non-null store
7576    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7577    GOTO_OPCODE(ip)                     @ jump to next instruction
7578
7579/* ------------------------------ */
7580    .balign 64
7581.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7582/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7583    /*
7584     * Handle an optimized virtual method call.
7585     *
7586     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7587     */
7588    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7589    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7590    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7591    FETCH(r1, 1)                        @ r1<- BBBB
7592    .if     (!0)
7593    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7594    .endif
7595    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7596    cmp     r2, #0                      @ is "this" null?
7597    beq     common_errNullObject        @ null "this", throw exception
7598    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7599    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7600    EXPORT_PC()                         @ invoke must export
7601    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7602    bl      common_invokeMethodNoRange @ continue on
7603
7604/* ------------------------------ */
7605    .balign 64
7606.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7607/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7608/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7609    /*
7610     * Handle an optimized virtual method call.
7611     *
7612     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7613     */
7614    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7615    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7616    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7617    FETCH(r1, 1)                        @ r1<- BBBB
7618    .if     (!1)
7619    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7620    .endif
7621    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7622    cmp     r2, #0                      @ is "this" null?
7623    beq     common_errNullObject        @ null "this", throw exception
7624    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7625    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7626    EXPORT_PC()                         @ invoke must export
7627    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7628    bl      common_invokeMethodRange @ continue on
7629
7630
7631/* ------------------------------ */
7632    .balign 64
7633.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7634/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7635    /*
7636     * Handle an optimized "super" method call.
7637     *
7638     * for: [opt] invoke-super-quick, invoke-super-quick/range
7639     */
7640    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7641    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7642    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7643    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7644    .if     (!0)
7645    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7646    .endif
7647    FETCH(r1, 1)                        @ r1<- BBBB
7648    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7649    EXPORT_PC()                         @ must export for invoke
7650    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7651    GET_VREG(r3, r10)                   @ r3<- "this"
7652    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7653    cmp     r3, #0                      @ null "this" ref?
7654    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7655    beq     common_errNullObject        @ "this" is null, throw exception
7656    bl      common_invokeMethodNoRange @ continue on
7657
7658/* ------------------------------ */
7659    .balign 64
7660.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7661/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7662/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7663    /*
7664     * Handle an optimized "super" method call.
7665     *
7666     * for: [opt] invoke-super-quick, invoke-super-quick/range
7667     */
7668    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7669    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7670    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7671    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7672    .if     (!1)
7673    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7674    .endif
7675    FETCH(r1, 1)                        @ r1<- BBBB
7676    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7677    EXPORT_PC()                         @ must export for invoke
7678    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7679    GET_VREG(r3, r10)                   @ r3<- "this"
7680    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7681    cmp     r3, #0                      @ null "this" ref?
7682    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7683    beq     common_errNullObject        @ "this" is null, throw exception
7684    bl      common_invokeMethodRange @ continue on
7685
7686
7687/* ------------------------------ */
7688    .balign 64
7689.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
7690/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
7691/* File: armv5te/OP_IPUT_OBJECT.S */
7692    /*
7693     * 32-bit instance field put.
7694     *
7695     * for: iput-object, iput-object-volatile
7696     */
7697    /* op vA, vB, field@CCCC */
7698    mov     r0, rINST, lsr #12          @ r0<- B
7699    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7700    FETCH(r1, 1)                        @ r1<- field ref CCCC
7701    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7702    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7703    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7704    cmp     r0, #0                      @ is resolved entry null?
7705    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
77068:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7707    EXPORT_PC()                         @ resolve() could throw
7708    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7709    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7710    cmp     r0, #0                      @ success?
7711    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
7712    b       common_exceptionThrown
7713
7714
7715/* ------------------------------ */
7716    .balign 64
7717.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
7718/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
7719/* File: armv5te/OP_SGET.S */
7720    /*
7721     * General 32-bit SGET handler.
7722     *
7723     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7724     */
7725    /* op vAA, field@BBBB */
7726    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7727    FETCH(r1, 1)                        @ r1<- field ref BBBB
7728    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7729    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7730    cmp     r0, #0                      @ is resolved entry null?
7731    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
7732.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
7733    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7734    SMP_DMB                            @ acquiring load
7735    mov     r2, rINST, lsr #8           @ r2<- AA
7736    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7737    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7738    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7739    GOTO_OPCODE(ip)                     @ jump to next instruction
7740
7741
7742/* ------------------------------ */
7743    .balign 64
7744.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
7745/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
7746/* File: armv5te/OP_SPUT_OBJECT.S */
7747    /*
7748     * 32-bit SPUT handler for objects
7749     *
7750     * for: sput-object, sput-object-volatile
7751     */
7752    /* op vAA, field@BBBB */
7753    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7754    FETCH(r1, 1)                        @ r1<- field ref BBBB
7755    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7756    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7757    cmp     r0, #0                      @ is resolved entry null?
7758    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
7759    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7760    EXPORT_PC()                         @ resolve() could throw, so export now
7761    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7762    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
7763    cmp     r0, #0                      @ success?
7764    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
7765    b       common_exceptionThrown      @ no, handle exception
7766
7767
7768
7769/* ------------------------------ */
7770    .balign 64
7771.L_OP_UNUSED_FF: /* 0xff */
7772/* File: armv5te/OP_UNUSED_FF.S */
7773/* File: armv5te/unused.S */
7774    bl      common_abort
7775
7776
7777
7778    .balign 64
7779    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
7780    .global dvmAsmInstructionEnd
7781dvmAsmInstructionEnd:
7782
7783/*
7784 * ===========================================================================
7785 *  Sister implementations
7786 * ===========================================================================
7787 */
7788    .global dvmAsmSisterStart
7789    .type   dvmAsmSisterStart, %function
7790    .text
7791    .balign 4
7792dvmAsmSisterStart:
7793
7794/* continuation for OP_CONST_STRING */
7795
7796    /*
7797     * Continuation if the String has not yet been resolved.
7798     *  r1: BBBB (String ref)
7799     *  r9: target register
7800     */
7801.LOP_CONST_STRING_resolve:
7802    EXPORT_PC()
7803    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7804    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7805    bl      dvmResolveString            @ r0<- String reference
7806    cmp     r0, #0                      @ failed?
7807    beq     common_exceptionThrown      @ yup, handle the exception
7808    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7809    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7810    SET_VREG(r0, r9)                    @ vAA<- r0
7811    GOTO_OPCODE(ip)                     @ jump to next instruction
7812
7813/* continuation for OP_CONST_STRING_JUMBO */
7814
7815    /*
7816     * Continuation if the String has not yet been resolved.
7817     *  r1: BBBBBBBB (String ref)
7818     *  r9: target register
7819     */
7820.LOP_CONST_STRING_JUMBO_resolve:
7821    EXPORT_PC()
7822    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7823    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7824    bl      dvmResolveString            @ r0<- String reference
7825    cmp     r0, #0                      @ failed?
7826    beq     common_exceptionThrown      @ yup, handle the exception
7827    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7828    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7829    SET_VREG(r0, r9)                    @ vAA<- r0
7830    GOTO_OPCODE(ip)                     @ jump to next instruction
7831
7832/* continuation for OP_CONST_CLASS */
7833
7834    /*
7835     * Continuation if the Class has not yet been resolved.
7836     *  r1: BBBB (Class ref)
7837     *  r9: target register
7838     */
7839.LOP_CONST_CLASS_resolve:
7840    EXPORT_PC()
7841    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
7842    mov     r2, #1                      @ r2<- true
7843    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7844    bl      dvmResolveClass             @ r0<- Class reference
7845    cmp     r0, #0                      @ failed?
7846    beq     common_exceptionThrown      @ yup, handle the exception
7847    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7848    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7849    SET_VREG(r0, r9)                    @ vAA<- r0
7850    GOTO_OPCODE(ip)                     @ jump to next instruction
7851
7852/* continuation for OP_CHECK_CAST */
7853
7854    /*
7855     * Trivial test failed, need to perform full check.  This is common.
7856     *  r0 holds obj->clazz
7857     *  r1 holds class resolved from BBBB
7858     *  r9 holds object
7859     */
7860.LOP_CHECK_CAST_fullcheck:
7861    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7862    cmp     r0, #0                      @ failed?
7863    bne     .LOP_CHECK_CAST_okay            @ no, success
7864
7865    @ A cast has failed.  We need to throw a ClassCastException with the
7866    @ class of the object that failed to be cast.
7867    EXPORT_PC()                         @ about to throw
7868    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
7869    ldr     r0, .LstrClassCastExceptionPtr
7870    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
7871    bl      dvmThrowExceptionWithClassMessage
7872    b       common_exceptionThrown
7873
7874    /*
7875     * Resolution required.  This is the least-likely path.
7876     *
7877     *  r2 holds BBBB
7878     *  r9 holds object
7879     */
7880.LOP_CHECK_CAST_resolve:
7881    EXPORT_PC()                         @ resolve() could throw
7882    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7883    mov     r1, r2                      @ r1<- BBBB
7884    mov     r2, #0                      @ r2<- false
7885    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7886    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7887    cmp     r0, #0                      @ got null?
7888    beq     common_exceptionThrown      @ yes, handle exception
7889    mov     r1, r0                      @ r1<- class resolved from BBB
7890    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
7891    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
7892
7893.LstrClassCastExceptionPtr:
7894    .word   .LstrClassCastException
7895
7896/* continuation for OP_INSTANCE_OF */
7897
7898    /*
7899     * Trivial test failed, need to perform full check.  This is common.
7900     *  r0 holds obj->clazz
7901     *  r1 holds class resolved from BBBB
7902     *  r9 holds A
7903     */
7904.LOP_INSTANCE_OF_fullcheck:
7905    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
7906    @ fall through to OP_INSTANCE_OF_store
7907
7908    /*
7909     * r0 holds boolean result
7910     * r9 holds A
7911     */
7912.LOP_INSTANCE_OF_store:
7913    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7914    SET_VREG(r0, r9)                    @ vA<- r0
7915    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7916    GOTO_OPCODE(ip)                     @ jump to next instruction
7917
7918    /*
7919     * Trivial test succeeded, save and bail.
7920     *  r9 holds A
7921     */
7922.LOP_INSTANCE_OF_trivial:
7923    mov     r0, #1                      @ indicate success
7924    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
7925    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7926    SET_VREG(r0, r9)                    @ vA<- r0
7927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7928    GOTO_OPCODE(ip)                     @ jump to next instruction
7929
7930    /*
7931     * Resolution required.  This is the least-likely path.
7932     *
7933     *  r3 holds BBBB
7934     *  r9 holds A
7935     */
7936.LOP_INSTANCE_OF_resolve:
7937    EXPORT_PC()                         @ resolve() could throw
7938    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7939    mov     r1, r3                      @ r1<- BBBB
7940    mov     r2, #1                      @ r2<- true
7941    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
7942    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7943    cmp     r0, #0                      @ got null?
7944    beq     common_exceptionThrown      @ yes, handle exception
7945    mov     r1, r0                      @ r1<- class resolved from BBB
7946    mov     r3, rINST, lsr #12          @ r3<- B
7947    GET_VREG(r0, r3)                    @ r0<- vB (object)
7948    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
7949    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
7950
7951/* continuation for OP_NEW_INSTANCE */
7952
7953    .balign 32                          @ minimize cache lines
7954.LOP_NEW_INSTANCE_finish: @ r0=new object
7955    mov     r3, rINST, lsr #8           @ r3<- AA
7956    cmp     r0, #0                      @ failed?
7957    beq     common_exceptionThrown      @ yes, handle the exception
7958    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7959    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7960    SET_VREG(r0, r3)                    @ vAA<- r0
7961    GOTO_OPCODE(ip)                     @ jump to next instruction
7962
7963    /*
7964     * Class initialization required.
7965     *
7966     *  r0 holds class object
7967     */
7968.LOP_NEW_INSTANCE_needinit:
7969    mov     r9, r0                      @ save r0
7970    bl      dvmInitClass                @ initialize class
7971    cmp     r0, #0                      @ check boolean result
7972    mov     r0, r9                      @ restore r0
7973    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
7974    b       common_exceptionThrown      @ failed, deal with init exception
7975
7976    /*
7977     * Resolution required.  This is the least-likely path.
7978     *
7979     *  r1 holds BBBB
7980     */
7981.LOP_NEW_INSTANCE_resolve:
7982    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
7983    mov     r2, #0                      @ r2<- false
7984    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
7985    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
7986    cmp     r0, #0                      @ got null?
7987    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
7988    b       common_exceptionThrown      @ yes, handle exception
7989
7990.LstrInstantiationErrorPtr:
7991    .word   .LstrInstantiationError
7992
7993/* continuation for OP_NEW_ARRAY */
7994
7995
7996    /*
7997     * Resolve class.  (This is an uncommon case.)
7998     *
7999     *  r1 holds array length
8000     *  r2 holds class ref CCCC
8001     */
8002.LOP_NEW_ARRAY_resolve:
8003    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8004    mov     r9, r1                      @ r9<- length (save)
8005    mov     r1, r2                      @ r1<- CCCC
8006    mov     r2, #0                      @ r2<- false
8007    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8008    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8009    cmp     r0, #0                      @ got null?
8010    mov     r1, r9                      @ r1<- length (restore)
8011    beq     common_exceptionThrown      @ yes, handle exception
8012    @ fall through to OP_NEW_ARRAY_finish
8013
8014    /*
8015     * Finish allocation.
8016     *
8017     *  r0 holds class
8018     *  r1 holds array length
8019     */
8020.LOP_NEW_ARRAY_finish:
8021    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8022    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8023    cmp     r0, #0                      @ failed?
8024    mov     r2, rINST, lsr #8           @ r2<- A+
8025    beq     common_exceptionThrown      @ yes, handle the exception
8026    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8027    and     r2, r2, #15                 @ r2<- A
8028    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8029    SET_VREG(r0, r2)                    @ vA<- r0
8030    GOTO_OPCODE(ip)                     @ jump to next instruction
8031
8032/* continuation for OP_FILLED_NEW_ARRAY */
8033
8034    /*
8035     * On entry:
8036     *  r0 holds array class
8037     *  r10 holds AA or BA
8038     */
8039.LOP_FILLED_NEW_ARRAY_continue:
8040    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8041    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8042    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8043    .if     0
8044    mov     r1, r10                     @ r1<- AA (length)
8045    .else
8046    mov     r1, r10, lsr #4             @ r1<- B (length)
8047    .endif
8048    cmp     rINST, #'I'                 @ array of ints?
8049    cmpne   rINST, #'L'                 @ array of objects?
8050    cmpne   rINST, #'['                 @ array of arrays?
8051    mov     r9, r1                      @ save length in r9
8052    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8053    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8054    cmp     r0, #0                      @ null return?
8055    beq     common_exceptionThrown      @ alloc failed, handle exception
8056
8057    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8058    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8059    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8060    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8061    subs    r9, r9, #1                  @ length--, check for neg
8062    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8063    bmi     2f                          @ was zero, bail
8064
8065    @ copy values from registers into the array
8066    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8067    .if     0
8068    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
80691:  ldr     r3, [r2], #4                @ r3<- *r2++
8070    subs    r9, r9, #1                  @ count--
8071    str     r3, [r0], #4                @ *contents++ = vX
8072    bpl     1b
8073    @ continue at 2
8074    .else
8075    cmp     r9, #4                      @ length was initially 5?
8076    and     r2, r10, #15                @ r2<- A
8077    bne     1f                          @ <= 4 args, branch
8078    GET_VREG(r3, r2)                    @ r3<- vA
8079    sub     r9, r9, #1                  @ count--
8080    str     r3, [r0, #16]               @ contents[4] = vA
80811:  and     r2, r1, #15                 @ r2<- F/E/D/C
8082    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8083    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8084    subs    r9, r9, #1                  @ count--
8085    str     r3, [r0], #4                @ *contents++ = vX
8086    bpl     1b
8087    @ continue at 2
8088    .endif
8089
80902:
8091    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8092    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8093    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8094    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8095    cmp     r1, #'I'                         @ Is int array?
8096    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
8097    GOTO_OPCODE(ip)                          @ execute it
8098
8099    /*
8100     * Throw an exception indicating that we have not implemented this
8101     * mode of filled-new-array.
8102     */
8103.LOP_FILLED_NEW_ARRAY_notimpl:
8104    ldr     r0, .L_strInternalError
8105    ldr     r1, .L_strFilledNewArrayNotImpl
8106    bl      dvmThrowException
8107    b       common_exceptionThrown
8108
8109    .if     (!0)                 @ define in one or the other, not both
8110.L_strFilledNewArrayNotImpl:
8111    .word   .LstrFilledNewArrayNotImpl
8112.L_strInternalError:
8113    .word   .LstrInternalError
8114    .endif
8115
8116/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8117
8118    /*
8119     * On entry:
8120     *  r0 holds array class
8121     *  r10 holds AA or BA
8122     */
8123.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8124    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8125    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8126    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8127    .if     1
8128    mov     r1, r10                     @ r1<- AA (length)
8129    .else
8130    mov     r1, r10, lsr #4             @ r1<- B (length)
8131    .endif
8132    cmp     rINST, #'I'                 @ array of ints?
8133    cmpne   rINST, #'L'                 @ array of objects?
8134    cmpne   rINST, #'['                 @ array of arrays?
8135    mov     r9, r1                      @ save length in r9
8136    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8137    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8138    cmp     r0, #0                      @ null return?
8139    beq     common_exceptionThrown      @ alloc failed, handle exception
8140
8141    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8142    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8143    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8144    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8145    subs    r9, r9, #1                  @ length--, check for neg
8146    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8147    bmi     2f                          @ was zero, bail
8148
8149    @ copy values from registers into the array
8150    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8151    .if     1
8152    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
81531:  ldr     r3, [r2], #4                @ r3<- *r2++
8154    subs    r9, r9, #1                  @ count--
8155    str     r3, [r0], #4                @ *contents++ = vX
8156    bpl     1b
8157    @ continue at 2
8158    .else
8159    cmp     r9, #4                      @ length was initially 5?
8160    and     r2, r10, #15                @ r2<- A
8161    bne     1f                          @ <= 4 args, branch
8162    GET_VREG(r3, r2)                    @ r3<- vA
8163    sub     r9, r9, #1                  @ count--
8164    str     r3, [r0, #16]               @ contents[4] = vA
81651:  and     r2, r1, #15                 @ r2<- F/E/D/C
8166    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8167    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8168    subs    r9, r9, #1                  @ count--
8169    str     r3, [r0], #4                @ *contents++ = vX
8170    bpl     1b
8171    @ continue at 2
8172    .endif
8173
81742:
8175    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8176    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8177    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8178    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8179    cmp     r1, #'I'                         @ Is int array?
8180    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card if not
8181    GOTO_OPCODE(ip)                          @ execute it
8182
8183    /*
8184     * Throw an exception indicating that we have not implemented this
8185     * mode of filled-new-array.
8186     */
8187.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8188    ldr     r0, .L_strInternalError
8189    ldr     r1, .L_strFilledNewArrayNotImpl
8190    bl      dvmThrowException
8191    b       common_exceptionThrown
8192
8193    .if     (!1)                 @ define in one or the other, not both
8194.L_strFilledNewArrayNotImpl:
8195    .word   .LstrFilledNewArrayNotImpl
8196.L_strInternalError:
8197    .word   .LstrInternalError
8198    .endif
8199
8200/* continuation for OP_CMPL_FLOAT */
8201.LOP_CMPL_FLOAT_finish:
8202    SET_VREG(r0, r9)                    @ vAA<- r0
8203    GOTO_OPCODE(ip)                     @ jump to next instruction
8204
8205/* continuation for OP_CMPG_FLOAT */
8206.LOP_CMPG_FLOAT_finish:
8207    SET_VREG(r0, r9)                    @ vAA<- r0
8208    GOTO_OPCODE(ip)                     @ jump to next instruction
8209
8210/* continuation for OP_CMPL_DOUBLE */
8211.LOP_CMPL_DOUBLE_finish:
8212    SET_VREG(r0, r9)                    @ vAA<- r0
8213    GOTO_OPCODE(ip)                     @ jump to next instruction
8214
8215/* continuation for OP_CMPG_DOUBLE */
8216.LOP_CMPG_DOUBLE_finish:
8217    SET_VREG(r0, r9)                    @ vAA<- r0
8218    GOTO_OPCODE(ip)                     @ jump to next instruction
8219
8220/* continuation for OP_CMP_LONG */
8221
8222.LOP_CMP_LONG_less:
8223    mvn     r1, #0                      @ r1<- -1
8224    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8225    @ instead, we just replicate the tail end.
8226    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8227    SET_VREG(r1, r9)                    @ vAA<- r1
8228    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8229    GOTO_OPCODE(ip)                     @ jump to next instruction
8230
8231.LOP_CMP_LONG_greater:
8232    mov     r1, #1                      @ r1<- 1
8233    @ fall through to _finish
8234
8235.LOP_CMP_LONG_finish:
8236    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8237    SET_VREG(r1, r9)                    @ vAA<- r1
8238    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8239    GOTO_OPCODE(ip)                     @ jump to next instruction
8240
8241/* continuation for OP_AGET_WIDE */
8242
8243.LOP_AGET_WIDE_finish:
8244    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8245    ldrd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8246    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8247    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8248    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8249    GOTO_OPCODE(ip)                     @ jump to next instruction
8250
8251/* continuation for OP_APUT_WIDE */
8252
8253.LOP_APUT_WIDE_finish:
8254    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8255    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8256    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8257    strd    r2, [r0, #offArrayObject_contents]  @ r2/r3<- vBB[vCC]
8258    GOTO_OPCODE(ip)                     @ jump to next instruction
8259
8260/* continuation for OP_APUT_OBJECT */
8261    /*
8262     * On entry:
8263     *  r1 = vBB (arrayObj)
8264     *  r9 = vAA (obj)
8265     *  r10 = offset into array (vBB + vCC * width)
8266     */
8267.LOP_APUT_OBJECT_finish:
8268    cmp     r9, #0                      @ storing null reference?
8269    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8270    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8271    ldr     r1, [r1, #offObject_clazz]  @ r1<- arrayObj->clazz
8272    bl      dvmCanPutArrayElement       @ test object type vs. array type
8273    cmp     r0, #0                      @ okay?
8274    beq     common_errArrayStore        @ no
8275    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8276    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8277    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8278    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8279    str     r9, [r10]                   @ vBB[vCC]<- vAA
8280    strb    r2, [r2, r10, lsr #GC_CARD_SHIFT]    @ mark card
8281    GOTO_OPCODE(ip)                     @ jump to next instruction
8282.LOP_APUT_OBJECT_skip_check:
8283    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8284    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8285    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8286    GOTO_OPCODE(ip)                     @ jump to next instruction
8287
8288/* continuation for OP_IGET */
8289
8290    /*
8291     * Currently:
8292     *  r0 holds resolved field
8293     *  r9 holds object
8294     */
8295.LOP_IGET_finish:
8296    @bl      common_squeak0
8297    cmp     r9, #0                      @ check object for null
8298    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8299    beq     common_errNullObject        @ object was null
8300    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8301    @ no-op                             @ acquiring load
8302    mov     r2, rINST, lsr #8           @ r2<- A+
8303    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8304    and     r2, r2, #15                 @ r2<- A
8305    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8306    SET_VREG(r0, r2)                    @ fp[A]<- r0
8307    GOTO_OPCODE(ip)                     @ jump to next instruction
8308
8309/* continuation for OP_IGET_WIDE */
8310
8311    /*
8312     * Currently:
8313     *  r0 holds resolved field
8314     *  r9 holds object
8315     */
8316.LOP_IGET_WIDE_finish:
8317    cmp     r9, #0                      @ check object for null
8318    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8319    beq     common_errNullObject        @ object was null
8320    .if     0
8321    add     r0, r9, r3                  @ r0<- address of field
8322    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8323    .else
8324    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
8325    .endif
8326    mov     r2, rINST, lsr #8           @ r2<- A+
8327    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8328    and     r2, r2, #15                 @ r2<- A
8329    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8330    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8331    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8332    GOTO_OPCODE(ip)                     @ jump to next instruction
8333
8334/* continuation for OP_IGET_OBJECT */
8335
8336    /*
8337     * Currently:
8338     *  r0 holds resolved field
8339     *  r9 holds object
8340     */
8341.LOP_IGET_OBJECT_finish:
8342    @bl      common_squeak0
8343    cmp     r9, #0                      @ check object for null
8344    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8345    beq     common_errNullObject        @ object was null
8346    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8347    @ no-op                             @ acquiring load
8348    mov     r2, rINST, lsr #8           @ r2<- A+
8349    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8350    and     r2, r2, #15                 @ r2<- A
8351    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8352    SET_VREG(r0, r2)                    @ fp[A]<- r0
8353    GOTO_OPCODE(ip)                     @ jump to next instruction
8354
8355/* continuation for OP_IGET_BOOLEAN */
8356
8357    /*
8358     * Currently:
8359     *  r0 holds resolved field
8360     *  r9 holds object
8361     */
8362.LOP_IGET_BOOLEAN_finish:
8363    @bl      common_squeak1
8364    cmp     r9, #0                      @ check object for null
8365    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8366    beq     common_errNullObject        @ object was null
8367    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8368    @ no-op                             @ acquiring load
8369    mov     r2, rINST, lsr #8           @ r2<- A+
8370    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8371    and     r2, r2, #15                 @ r2<- A
8372    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8373    SET_VREG(r0, r2)                    @ fp[A]<- r0
8374    GOTO_OPCODE(ip)                     @ jump to next instruction
8375
8376/* continuation for OP_IGET_BYTE */
8377
8378    /*
8379     * Currently:
8380     *  r0 holds resolved field
8381     *  r9 holds object
8382     */
8383.LOP_IGET_BYTE_finish:
8384    @bl      common_squeak2
8385    cmp     r9, #0                      @ check object for null
8386    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8387    beq     common_errNullObject        @ object was null
8388    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8389    @ no-op                             @ acquiring load
8390    mov     r2, rINST, lsr #8           @ r2<- A+
8391    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8392    and     r2, r2, #15                 @ r2<- A
8393    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8394    SET_VREG(r0, r2)                    @ fp[A]<- r0
8395    GOTO_OPCODE(ip)                     @ jump to next instruction
8396
8397/* continuation for OP_IGET_CHAR */
8398
8399    /*
8400     * Currently:
8401     *  r0 holds resolved field
8402     *  r9 holds object
8403     */
8404.LOP_IGET_CHAR_finish:
8405    @bl      common_squeak3
8406    cmp     r9, #0                      @ check object for null
8407    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8408    beq     common_errNullObject        @ object was null
8409    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8410    @ no-op                             @ acquiring load
8411    mov     r2, rINST, lsr #8           @ r2<- A+
8412    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8413    and     r2, r2, #15                 @ r2<- A
8414    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8415    SET_VREG(r0, r2)                    @ fp[A]<- r0
8416    GOTO_OPCODE(ip)                     @ jump to next instruction
8417
8418/* continuation for OP_IGET_SHORT */
8419
8420    /*
8421     * Currently:
8422     *  r0 holds resolved field
8423     *  r9 holds object
8424     */
8425.LOP_IGET_SHORT_finish:
8426    @bl      common_squeak4
8427    cmp     r9, #0                      @ check object for null
8428    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8429    beq     common_errNullObject        @ object was null
8430    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8431    @ no-op                             @ acquiring load
8432    mov     r2, rINST, lsr #8           @ r2<- A+
8433    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8434    and     r2, r2, #15                 @ r2<- A
8435    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8436    SET_VREG(r0, r2)                    @ fp[A]<- r0
8437    GOTO_OPCODE(ip)                     @ jump to next instruction
8438
8439/* continuation for OP_IPUT */
8440
8441    /*
8442     * Currently:
8443     *  r0 holds resolved field
8444     *  r9 holds object
8445     */
8446.LOP_IPUT_finish:
8447    @bl      common_squeak0
8448    mov     r1, rINST, lsr #8           @ r1<- A+
8449    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8450    and     r1, r1, #15                 @ r1<- A
8451    cmp     r9, #0                      @ check object for null
8452    GET_VREG(r0, r1)                    @ r0<- fp[A]
8453    beq     common_errNullObject        @ object was null
8454    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8455    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8456    @ no-op                             @ releasing store
8457    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8458    GOTO_OPCODE(ip)                     @ jump to next instruction
8459
8460/* continuation for OP_IPUT_WIDE */
8461
8462    /*
8463     * Currently:
8464     *  r0 holds resolved field
8465     *  r9 holds object
8466     */
8467.LOP_IPUT_WIDE_finish:
8468    mov     r2, rINST, lsr #8           @ r2<- A+
8469    cmp     r9, #0                      @ check object for null
8470    and     r2, r2, #15                 @ r2<- A
8471    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8472    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8473    beq     common_errNullObject        @ object was null
8474    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8475    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8476    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8477    .if     0
8478    add     r2, r9, r3                  @ r2<- target address
8479    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8480    .else
8481    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
8482    .endif
8483    GOTO_OPCODE(r10)                    @ jump to next instruction
8484
8485/* continuation for OP_IPUT_OBJECT */
8486
8487    /*
8488     * Currently:
8489     *  r0 holds resolved field
8490     *  r9 holds object
8491     */
8492.LOP_IPUT_OBJECT_finish:
8493    @bl      common_squeak0
8494    mov     r1, rINST, lsr #8           @ r1<- A+
8495    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8496    and     r1, r1, #15                 @ r1<- A
8497    cmp     r9, #0                      @ check object for null
8498    GET_VREG(r0, r1)                    @ r0<- fp[A]
8499    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8500    beq     common_errNullObject        @ object was null
8501    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8502    add     r9, r3                      @ r9<- direct ptr to target location
8503    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8504    @ no-op                             @ releasing store
8505    str     r0, [r9]                    @ obj.field (8/16/32 bits)<- r0
8506    cmp     r0, #0                      @ stored a null reference?
8507    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8508    GOTO_OPCODE(ip)                     @ jump to next instruction
8509
8510/* continuation for OP_IPUT_BOOLEAN */
8511
8512    /*
8513     * Currently:
8514     *  r0 holds resolved field
8515     *  r9 holds object
8516     */
8517.LOP_IPUT_BOOLEAN_finish:
8518    @bl      common_squeak1
8519    mov     r1, rINST, lsr #8           @ r1<- A+
8520    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8521    and     r1, r1, #15                 @ r1<- A
8522    cmp     r9, #0                      @ check object for null
8523    GET_VREG(r0, r1)                    @ r0<- fp[A]
8524    beq     common_errNullObject        @ object was null
8525    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8526    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8527    @ no-op                             @ releasing store
8528    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8529    GOTO_OPCODE(ip)                     @ jump to next instruction
8530
8531/* continuation for OP_IPUT_BYTE */
8532
8533    /*
8534     * Currently:
8535     *  r0 holds resolved field
8536     *  r9 holds object
8537     */
8538.LOP_IPUT_BYTE_finish:
8539    @bl      common_squeak2
8540    mov     r1, rINST, lsr #8           @ r1<- A+
8541    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8542    and     r1, r1, #15                 @ r1<- A
8543    cmp     r9, #0                      @ check object for null
8544    GET_VREG(r0, r1)                    @ r0<- fp[A]
8545    beq     common_errNullObject        @ object was null
8546    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8547    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8548    @ no-op                             @ releasing store
8549    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8550    GOTO_OPCODE(ip)                     @ jump to next instruction
8551
8552/* continuation for OP_IPUT_CHAR */
8553
8554    /*
8555     * Currently:
8556     *  r0 holds resolved field
8557     *  r9 holds object
8558     */
8559.LOP_IPUT_CHAR_finish:
8560    @bl      common_squeak3
8561    mov     r1, rINST, lsr #8           @ r1<- A+
8562    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8563    and     r1, r1, #15                 @ r1<- A
8564    cmp     r9, #0                      @ check object for null
8565    GET_VREG(r0, r1)                    @ r0<- fp[A]
8566    beq     common_errNullObject        @ object was null
8567    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8568    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8569    @ no-op                             @ releasing store
8570    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8571    GOTO_OPCODE(ip)                     @ jump to next instruction
8572
8573/* continuation for OP_IPUT_SHORT */
8574
8575    /*
8576     * Currently:
8577     *  r0 holds resolved field
8578     *  r9 holds object
8579     */
8580.LOP_IPUT_SHORT_finish:
8581    @bl      common_squeak4
8582    mov     r1, rINST, lsr #8           @ r1<- A+
8583    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8584    and     r1, r1, #15                 @ r1<- A
8585    cmp     r9, #0                      @ check object for null
8586    GET_VREG(r0, r1)                    @ r0<- fp[A]
8587    beq     common_errNullObject        @ object was null
8588    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8589    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8590    @ no-op                             @ releasing store
8591    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8592    GOTO_OPCODE(ip)                     @ jump to next instruction
8593
8594/* continuation for OP_SGET */
8595
8596    /*
8597     * Continuation if the field has not yet been resolved.
8598     *  r1: BBBB field ref
8599     */
8600.LOP_SGET_resolve:
8601    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8602    EXPORT_PC()                         @ resolve() could throw, so export now
8603    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8604    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8605    cmp     r0, #0                      @ success?
8606    bne     .LOP_SGET_finish          @ yes, finish
8607    b       common_exceptionThrown      @ no, handle exception
8608
8609/* continuation for OP_SGET_WIDE */
8610
8611    /*
8612     * Continuation if the field has not yet been resolved.
8613     *  r1: BBBB field ref
8614     *
8615     * Returns StaticField pointer in r0.
8616     */
8617.LOP_SGET_WIDE_resolve:
8618    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8619    EXPORT_PC()                         @ resolve() could throw, so export now
8620    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8621    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8622    cmp     r0, #0                      @ success?
8623    bne     .LOP_SGET_WIDE_finish          @ yes, finish
8624    b       common_exceptionThrown      @ no, handle exception
8625
8626/* continuation for OP_SGET_OBJECT */
8627
8628    /*
8629     * Continuation if the field has not yet been resolved.
8630     *  r1: BBBB field ref
8631     */
8632.LOP_SGET_OBJECT_resolve:
8633    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8634    EXPORT_PC()                         @ resolve() could throw, so export now
8635    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8636    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8637    cmp     r0, #0                      @ success?
8638    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
8639    b       common_exceptionThrown      @ no, handle exception
8640
8641/* continuation for OP_SGET_BOOLEAN */
8642
8643    /*
8644     * Continuation if the field has not yet been resolved.
8645     *  r1: BBBB field ref
8646     */
8647.LOP_SGET_BOOLEAN_resolve:
8648    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8649    EXPORT_PC()                         @ resolve() could throw, so export now
8650    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8651    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8652    cmp     r0, #0                      @ success?
8653    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
8654    b       common_exceptionThrown      @ no, handle exception
8655
8656/* continuation for OP_SGET_BYTE */
8657
8658    /*
8659     * Continuation if the field has not yet been resolved.
8660     *  r1: BBBB field ref
8661     */
8662.LOP_SGET_BYTE_resolve:
8663    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8664    EXPORT_PC()                         @ resolve() could throw, so export now
8665    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8666    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8667    cmp     r0, #0                      @ success?
8668    bne     .LOP_SGET_BYTE_finish          @ yes, finish
8669    b       common_exceptionThrown      @ no, handle exception
8670
8671/* continuation for OP_SGET_CHAR */
8672
8673    /*
8674     * Continuation if the field has not yet been resolved.
8675     *  r1: BBBB field ref
8676     */
8677.LOP_SGET_CHAR_resolve:
8678    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8679    EXPORT_PC()                         @ resolve() could throw, so export now
8680    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8681    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8682    cmp     r0, #0                      @ success?
8683    bne     .LOP_SGET_CHAR_finish          @ yes, finish
8684    b       common_exceptionThrown      @ no, handle exception
8685
8686/* continuation for OP_SGET_SHORT */
8687
8688    /*
8689     * Continuation if the field has not yet been resolved.
8690     *  r1: BBBB field ref
8691     */
8692.LOP_SGET_SHORT_resolve:
8693    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8694    EXPORT_PC()                         @ resolve() could throw, so export now
8695    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8696    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8697    cmp     r0, #0                      @ success?
8698    bne     .LOP_SGET_SHORT_finish          @ yes, finish
8699    b       common_exceptionThrown      @ no, handle exception
8700
8701/* continuation for OP_SPUT */
8702
8703    /*
8704     * Continuation if the field has not yet been resolved.
8705     *  r1: BBBB field ref
8706     */
8707.LOP_SPUT_resolve:
8708    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8709    EXPORT_PC()                         @ resolve() could throw, so export now
8710    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8711    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8712    cmp     r0, #0                      @ success?
8713    bne     .LOP_SPUT_finish          @ yes, finish
8714    b       common_exceptionThrown      @ no, handle exception
8715
8716/* continuation for OP_SPUT_WIDE */
8717
8718    /*
8719     * Continuation if the field has not yet been resolved.
8720     *  r1: BBBB field ref
8721     *  r9: &fp[AA]
8722     *
8723     * Returns StaticField pointer in r2.
8724     */
8725.LOP_SPUT_WIDE_resolve:
8726    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8727    EXPORT_PC()                         @ resolve() could throw, so export now
8728    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8729    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8730    cmp     r0, #0                      @ success?
8731    mov     r2, r0                      @ copy to r2
8732    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
8733    b       common_exceptionThrown      @ no, handle exception
8734
8735/* continuation for OP_SPUT_OBJECT */
8736.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
8737    mov     r2, rINST, lsr #8           @ r2<- AA
8738    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8739    GET_VREG(r1, r2)                    @ r1<- fp[AA]
8740    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8741    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8742    add     r0, #offStaticField_value   @ r0<- pointer to store target
8743    @ no-op                             @ releasing store
8744    str     r1, [r0]                    @ field<- vAA
8745    cmp     r1, #0                      @ stored a null object?
8746    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
8747    GOTO_OPCODE(ip)                     @ jump to next instruction
8748
8749/* continuation for OP_SPUT_BOOLEAN */
8750
8751    /*
8752     * Continuation if the field has not yet been resolved.
8753     *  r1: BBBB field ref
8754     */
8755.LOP_SPUT_BOOLEAN_resolve:
8756    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8757    EXPORT_PC()                         @ resolve() could throw, so export now
8758    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8759    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8760    cmp     r0, #0                      @ success?
8761    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
8762    b       common_exceptionThrown      @ no, handle exception
8763
8764/* continuation for OP_SPUT_BYTE */
8765
8766    /*
8767     * Continuation if the field has not yet been resolved.
8768     *  r1: BBBB field ref
8769     */
8770.LOP_SPUT_BYTE_resolve:
8771    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8772    EXPORT_PC()                         @ resolve() could throw, so export now
8773    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8774    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8775    cmp     r0, #0                      @ success?
8776    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
8777    b       common_exceptionThrown      @ no, handle exception
8778
8779/* continuation for OP_SPUT_CHAR */
8780
8781    /*
8782     * Continuation if the field has not yet been resolved.
8783     *  r1: BBBB field ref
8784     */
8785.LOP_SPUT_CHAR_resolve:
8786    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8787    EXPORT_PC()                         @ resolve() could throw, so export now
8788    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8789    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8790    cmp     r0, #0                      @ success?
8791    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
8792    b       common_exceptionThrown      @ no, handle exception
8793
8794/* continuation for OP_SPUT_SHORT */
8795
8796    /*
8797     * Continuation if the field has not yet been resolved.
8798     *  r1: BBBB field ref
8799     */
8800.LOP_SPUT_SHORT_resolve:
8801    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8802    EXPORT_PC()                         @ resolve() could throw, so export now
8803    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8804    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8805    cmp     r0, #0                      @ success?
8806    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
8807    b       common_exceptionThrown      @ no, handle exception
8808
8809/* continuation for OP_INVOKE_VIRTUAL */
8810
8811    /*
8812     * At this point:
8813     *  r0 = resolved base method
8814     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8815     */
8816.LOP_INVOKE_VIRTUAL_continue:
8817    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8818    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8819    cmp     r1, #0                      @ is "this" null?
8820    beq     common_errNullObject        @ null "this", throw exception
8821    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8822    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8823    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8824    bl      common_invokeMethodNoRange @ continue on
8825
8826/* continuation for OP_INVOKE_SUPER */
8827
8828    /*
8829     * At this point:
8830     *  r0 = resolved base method
8831     *  r9 = method->clazz
8832     */
8833.LOP_INVOKE_SUPER_continue:
8834    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8835    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8836    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8837    EXPORT_PC()                         @ must export for invoke
8838    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8839    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
8840    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8841    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8842    bl      common_invokeMethodNoRange @ continue on
8843
8844.LOP_INVOKE_SUPER_resolve:
8845    mov     r0, r9                      @ r0<- method->clazz
8846    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8847    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8848    cmp     r0, #0                      @ got null?
8849    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
8850    b       common_exceptionThrown      @ yes, handle exception
8851
8852    /*
8853     * Throw a NoSuchMethodError with the method name as the message.
8854     *  r0 = resolved base method
8855     */
8856.LOP_INVOKE_SUPER_nsm:
8857    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8858    b       common_errNoSuchMethod
8859
8860/* continuation for OP_INVOKE_DIRECT */
8861
8862    /*
8863     * On entry:
8864     *  r1 = reference (BBBB or CCCC)
8865     *  r10 = "this" register
8866     */
8867.LOP_INVOKE_DIRECT_resolve:
8868    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8869    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8870    mov     r2, #METHOD_DIRECT          @ resolver method type
8871    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8872    cmp     r0, #0                      @ got null?
8873    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8874    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
8875    b       common_exceptionThrown      @ yes, handle exception
8876
8877/* continuation for OP_INVOKE_VIRTUAL_RANGE */
8878
8879    /*
8880     * At this point:
8881     *  r0 = resolved base method
8882     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
8883     */
8884.LOP_INVOKE_VIRTUAL_RANGE_continue:
8885    GET_VREG(r1, r10)                   @ r1<- "this" ptr
8886    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8887    cmp     r1, #0                      @ is "this" null?
8888    beq     common_errNullObject        @ null "this", throw exception
8889    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
8890    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
8891    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
8892    bl      common_invokeMethodRange @ continue on
8893
8894/* continuation for OP_INVOKE_SUPER_RANGE */
8895
8896    /*
8897     * At this point:
8898     *  r0 = resolved base method
8899     *  r9 = method->clazz
8900     */
8901.LOP_INVOKE_SUPER_RANGE_continue:
8902    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
8903    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
8904    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
8905    EXPORT_PC()                         @ must export for invoke
8906    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
8907    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
8908    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
8909    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
8910    bl      common_invokeMethodRange @ continue on
8911
8912.LOP_INVOKE_SUPER_RANGE_resolve:
8913    mov     r0, r9                      @ r0<- method->clazz
8914    mov     r2, #METHOD_VIRTUAL         @ resolver method type
8915    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8916    cmp     r0, #0                      @ got null?
8917    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
8918    b       common_exceptionThrown      @ yes, handle exception
8919
8920    /*
8921     * Throw a NoSuchMethodError with the method name as the message.
8922     *  r0 = resolved base method
8923     */
8924.LOP_INVOKE_SUPER_RANGE_nsm:
8925    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
8926    b       common_errNoSuchMethod
8927
8928/* continuation for OP_INVOKE_DIRECT_RANGE */
8929
8930    /*
8931     * On entry:
8932     *  r1 = reference (BBBB or CCCC)
8933     *  r10 = "this" register
8934     */
8935.LOP_INVOKE_DIRECT_RANGE_resolve:
8936    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8937    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8938    mov     r2, #METHOD_DIRECT          @ resolver method type
8939    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
8940    cmp     r0, #0                      @ got null?
8941    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
8942    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
8943    b       common_exceptionThrown      @ yes, handle exception
8944
8945/* continuation for OP_FLOAT_TO_LONG */
8946/*
8947 * Convert the float in r0 to a long in r0/r1.
8948 *
8949 * We have to clip values to long min/max per the specification.  The
8950 * expected common case is a "reasonable" value that converts directly
8951 * to modest integer.  The EABI convert function isn't doing this for us.
8952 */
8953f2l_doconv:
8954    stmfd   sp!, {r4, lr}
8955    mov     r1, #0x5f000000             @ (float)maxlong
8956    mov     r4, r0
8957    bl      __aeabi_fcmpge              @ is arg >= maxlong?
8958    cmp     r0, #0                      @ nonzero == yes
8959    mvnne   r0, #0                      @ return maxlong (7fffffff)
8960    mvnne   r1, #0x80000000
8961    ldmnefd sp!, {r4, pc}
8962
8963    mov     r0, r4                      @ recover arg
8964    mov     r1, #0xdf000000             @ (float)minlong
8965    bl      __aeabi_fcmple              @ is arg <= minlong?
8966    cmp     r0, #0                      @ nonzero == yes
8967    movne   r0, #0                      @ return minlong (80000000)
8968    movne   r1, #0x80000000
8969    ldmnefd sp!, {r4, pc}
8970
8971    mov     r0, r4                      @ recover arg
8972    mov     r1, r4
8973    bl      __aeabi_fcmpeq              @ is arg == self?
8974    cmp     r0, #0                      @ zero == no
8975    moveq   r1, #0                      @ return zero for NaN
8976    ldmeqfd sp!, {r4, pc}
8977
8978    mov     r0, r4                      @ recover arg
8979    bl      __aeabi_f2lz                @ convert float to long
8980    ldmfd   sp!, {r4, pc}
8981
8982/* continuation for OP_DOUBLE_TO_LONG */
8983/*
8984 * Convert the double in r0/r1 to a long in r0/r1.
8985 *
8986 * We have to clip values to long min/max per the specification.  The
8987 * expected common case is a "reasonable" value that converts directly
8988 * to modest integer.  The EABI convert function isn't doing this for us.
8989 */
8990d2l_doconv:
8991    stmfd   sp!, {r4, r5, lr}           @ save regs
8992    mov     r3, #0x43000000             @ maxlong, as a double (high word)
8993    add     r3, #0x00e00000             @  0x43e00000
8994    mov     r2, #0                      @ maxlong, as a double (low word)
8995    sub     sp, sp, #4                  @ align for EABI
8996    mov     r4, r0                      @ save a copy of r0
8997    mov     r5, r1                      @  and r1
8998    bl      __aeabi_dcmpge              @ is arg >= maxlong?
8999    cmp     r0, #0                      @ nonzero == yes
9000    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9001    mvnne   r1, #0x80000000
9002    bne     1f
9003
9004    mov     r0, r4                      @ recover arg
9005    mov     r1, r5
9006    mov     r3, #0xc3000000             @ minlong, as a double (high word)
9007    add     r3, #0x00e00000             @  0xc3e00000
9008    mov     r2, #0                      @ minlong, as a double (low word)
9009    bl      __aeabi_dcmple              @ is arg <= minlong?
9010    cmp     r0, #0                      @ nonzero == yes
9011    movne   r0, #0                      @ return minlong (8000000000000000)
9012    movne   r1, #0x80000000
9013    bne     1f
9014
9015    mov     r0, r4                      @ recover arg
9016    mov     r1, r5
9017    mov     r2, r4                      @ compare against self
9018    mov     r3, r5
9019    bl      __aeabi_dcmpeq              @ is arg == self?
9020    cmp     r0, #0                      @ zero == no
9021    moveq   r1, #0                      @ return zero for NaN
9022    beq     1f
9023
9024    mov     r0, r4                      @ recover arg
9025    mov     r1, r5
9026    bl      __aeabi_d2lz                @ convert double to long
9027
90281:
9029    add     sp, sp, #4
9030    ldmfd   sp!, {r4, r5, pc}
9031
9032/* continuation for OP_MUL_LONG */
9033
9034.LOP_MUL_LONG_finish:
9035    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9036    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9037    GOTO_OPCODE(ip)                     @ jump to next instruction
9038
9039/* continuation for OP_SHL_LONG */
9040
9041.LOP_SHL_LONG_finish:
9042    mov     r0, r0, asl r2              @  r0<- r0 << r2
9043    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9044    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9045    GOTO_OPCODE(ip)                     @ jump to next instruction
9046
9047/* continuation for OP_SHR_LONG */
9048
9049.LOP_SHR_LONG_finish:
9050    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9051    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9052    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9053    GOTO_OPCODE(ip)                     @ jump to next instruction
9054
9055/* continuation for OP_USHR_LONG */
9056
9057.LOP_USHR_LONG_finish:
9058    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9059    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9060    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9061    GOTO_OPCODE(ip)                     @ jump to next instruction
9062
9063/* continuation for OP_SHL_LONG_2ADDR */
9064
9065.LOP_SHL_LONG_2ADDR_finish:
9066    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9067    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9068    GOTO_OPCODE(ip)                     @ jump to next instruction
9069
9070/* continuation for OP_SHR_LONG_2ADDR */
9071
9072.LOP_SHR_LONG_2ADDR_finish:
9073    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9074    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9075    GOTO_OPCODE(ip)                     @ jump to next instruction
9076
9077/* continuation for OP_USHR_LONG_2ADDR */
9078
9079.LOP_USHR_LONG_2ADDR_finish:
9080    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9081    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9082    GOTO_OPCODE(ip)                     @ jump to next instruction
9083
9084/* continuation for OP_IGET_VOLATILE */
9085
9086    /*
9087     * Currently:
9088     *  r0 holds resolved field
9089     *  r9 holds object
9090     */
9091.LOP_IGET_VOLATILE_finish:
9092    @bl      common_squeak0
9093    cmp     r9, #0                      @ check object for null
9094    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9095    beq     common_errNullObject        @ object was null
9096    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9097    SMP_DMB                            @ acquiring load
9098    mov     r2, rINST, lsr #8           @ r2<- A+
9099    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9100    and     r2, r2, #15                 @ r2<- A
9101    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9102    SET_VREG(r0, r2)                    @ fp[A]<- r0
9103    GOTO_OPCODE(ip)                     @ jump to next instruction
9104
9105/* continuation for OP_IPUT_VOLATILE */
9106
9107    /*
9108     * Currently:
9109     *  r0 holds resolved field
9110     *  r9 holds object
9111     */
9112.LOP_IPUT_VOLATILE_finish:
9113    @bl      common_squeak0
9114    mov     r1, rINST, lsr #8           @ r1<- A+
9115    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9116    and     r1, r1, #15                 @ r1<- A
9117    cmp     r9, #0                      @ check object for null
9118    GET_VREG(r0, r1)                    @ r0<- fp[A]
9119    beq     common_errNullObject        @ object was null
9120    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9121    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9122    SMP_DMB                            @ releasing store
9123    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9124    GOTO_OPCODE(ip)                     @ jump to next instruction
9125
9126/* continuation for OP_SGET_VOLATILE */
9127
9128    /*
9129     * Continuation if the field has not yet been resolved.
9130     *  r1: BBBB field ref
9131     */
9132.LOP_SGET_VOLATILE_resolve:
9133    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9134    EXPORT_PC()                         @ resolve() could throw, so export now
9135    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9136    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9137    cmp     r0, #0                      @ success?
9138    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9139    b       common_exceptionThrown      @ no, handle exception
9140
9141/* continuation for OP_SPUT_VOLATILE */
9142
9143    /*
9144     * Continuation if the field has not yet been resolved.
9145     *  r1: BBBB field ref
9146     */
9147.LOP_SPUT_VOLATILE_resolve:
9148    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9149    EXPORT_PC()                         @ resolve() could throw, so export now
9150    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9151    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9152    cmp     r0, #0                      @ success?
9153    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9154    b       common_exceptionThrown      @ no, handle exception
9155
9156/* continuation for OP_IGET_OBJECT_VOLATILE */
9157
9158    /*
9159     * Currently:
9160     *  r0 holds resolved field
9161     *  r9 holds object
9162     */
9163.LOP_IGET_OBJECT_VOLATILE_finish:
9164    @bl      common_squeak0
9165    cmp     r9, #0                      @ check object for null
9166    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9167    beq     common_errNullObject        @ object was null
9168    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9169    SMP_DMB                            @ acquiring load
9170    mov     r2, rINST, lsr #8           @ r2<- A+
9171    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9172    and     r2, r2, #15                 @ r2<- A
9173    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9174    SET_VREG(r0, r2)                    @ fp[A]<- r0
9175    GOTO_OPCODE(ip)                     @ jump to next instruction
9176
9177/* continuation for OP_IGET_WIDE_VOLATILE */
9178
9179    /*
9180     * Currently:
9181     *  r0 holds resolved field
9182     *  r9 holds object
9183     */
9184.LOP_IGET_WIDE_VOLATILE_finish:
9185    cmp     r9, #0                      @ check object for null
9186    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9187    beq     common_errNullObject        @ object was null
9188    .if     1
9189    add     r0, r9, r3                  @ r0<- address of field
9190    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9191    .else
9192    ldrd    r0, [r9, r3]                @ r0/r1<- obj.field (64-bit align ok)
9193    .endif
9194    mov     r2, rINST, lsr #8           @ r2<- A+
9195    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9196    and     r2, r2, #15                 @ r2<- A
9197    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9198    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9199    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9200    GOTO_OPCODE(ip)                     @ jump to next instruction
9201
9202/* continuation for OP_IPUT_WIDE_VOLATILE */
9203
9204    /*
9205     * Currently:
9206     *  r0 holds resolved field
9207     *  r9 holds object
9208     */
9209.LOP_IPUT_WIDE_VOLATILE_finish:
9210    mov     r2, rINST, lsr #8           @ r2<- A+
9211    cmp     r9, #0                      @ check object for null
9212    and     r2, r2, #15                 @ r2<- A
9213    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9214    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9215    beq     common_errNullObject        @ object was null
9216    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9217    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9218    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9219    .if     1
9220    add     r2, r9, r3                  @ r2<- target address
9221    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9222    .else
9223    strd    r0, [r9, r3]                @ obj.field (64 bits, aligned)<- r0/r1
9224    .endif
9225    GOTO_OPCODE(r10)                    @ jump to next instruction
9226
9227/* continuation for OP_SGET_WIDE_VOLATILE */
9228
9229    /*
9230     * Continuation if the field has not yet been resolved.
9231     *  r1: BBBB field ref
9232     *
9233     * Returns StaticField pointer in r0.
9234     */
9235.LOP_SGET_WIDE_VOLATILE_resolve:
9236    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9237    EXPORT_PC()                         @ resolve() could throw, so export now
9238    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9239    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9240    cmp     r0, #0                      @ success?
9241    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9242    b       common_exceptionThrown      @ no, handle exception
9243
9244/* continuation for OP_SPUT_WIDE_VOLATILE */
9245
9246    /*
9247     * Continuation if the field has not yet been resolved.
9248     *  r1: BBBB field ref
9249     *  r9: &fp[AA]
9250     *
9251     * Returns StaticField pointer in r2.
9252     */
9253.LOP_SPUT_WIDE_VOLATILE_resolve:
9254    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9255    EXPORT_PC()                         @ resolve() could throw, so export now
9256    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9257    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9258    cmp     r0, #0                      @ success?
9259    mov     r2, r0                      @ copy to r2
9260    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9261    b       common_exceptionThrown      @ no, handle exception
9262
9263/* continuation for OP_EXECUTE_INLINE */
9264
9265    /*
9266     * Extract args, call function.
9267     *  r0 = #of args (0-4)
9268     *  r10 = call index
9269     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9270     *
9271     * Other ideas:
9272     * - Use a jump table from the main piece to jump directly into the
9273     *   AND/LDR pairs.  Costs a data load, saves a branch.
9274     * - Have five separate pieces that do the loading, so we can work the
9275     *   interleave a little better.  Increases code size.
9276     */
9277.LOP_EXECUTE_INLINE_continue:
9278    rsb     r0, r0, #4                  @ r0<- 4-r0
9279    FETCH(r9, 2)                        @ r9<- FEDC
9280    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9281    bl      common_abort                @ (skipped due to ARM prefetch)
92824:  and     ip, r9, #0xf000             @ isolate F
9283    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
92843:  and     ip, r9, #0x0f00             @ isolate E
9285    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
92862:  and     ip, r9, #0x00f0             @ isolate D
9287    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
92881:  and     ip, r9, #0x000f             @ isolate C
9289    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
92900:
9291    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9292    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9293    @ (not reached)
9294
9295.LOP_EXECUTE_INLINE_table:
9296    .word   gDvmInlineOpsTable
9297
9298/* continuation for OP_EXECUTE_INLINE_RANGE */
9299
9300    /*
9301     * Extract args, call function.
9302     *  r0 = #of args (0-4)
9303     *  r10 = call index
9304     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9305     */
9306.LOP_EXECUTE_INLINE_RANGE_continue:
9307    rsb     r0, r0, #4                  @ r0<- 4-r0
9308    FETCH(r9, 2)                        @ r9<- CCCC
9309    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9310    bl      common_abort                @ (skipped due to ARM prefetch)
93114:  add     ip, r9, #3                  @ base+3
9312    GET_VREG(r3, ip)                    @ r3<- vBase[3]
93133:  add     ip, r9, #2                  @ base+2
9314    GET_VREG(r2, ip)                    @ r2<- vBase[2]
93152:  add     ip, r9, #1                  @ base+1
9316    GET_VREG(r1, ip)                    @ r1<- vBase[1]
93171:  add     ip, r9, #0                  @ (nop)
9318    GET_VREG(r0, ip)                    @ r0<- vBase[0]
93190:
9320    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9321    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9322    @ (not reached)
9323
9324.LOP_EXECUTE_INLINE_RANGE_table:
9325    .word   gDvmInlineOpsTable
9326
9327/* continuation for OP_IPUT_OBJECT_VOLATILE */
9328
9329    /*
9330     * Currently:
9331     *  r0 holds resolved field
9332     *  r9 holds object
9333     */
9334.LOP_IPUT_OBJECT_VOLATILE_finish:
9335    @bl      common_squeak0
9336    mov     r1, rINST, lsr #8           @ r1<- A+
9337    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9338    and     r1, r1, #15                 @ r1<- A
9339    cmp     r9, #0                      @ check object for null
9340    GET_VREG(r0, r1)                    @ r0<- fp[A]
9341    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9342    beq     common_errNullObject        @ object was null
9343    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9344    add     r9, r3                      @ r9<- direct ptr to target location
9345    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9346    SMP_DMB                            @ releasing store
9347    str     r0, [r9]                    @ obj.field (8/16/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    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9374    add     r0, #offStaticField_value   @ r0<- pointer to store target
9375    SMP_DMB                            @ releasing store
9376    str     r1, [r0]                    @ field<- vAA
9377    cmp     r1, #0                      @ stored a null object?
9378    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT]  @ mark card if not
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    GET_INST_OPCODE(ip)
9714    GOTO_OPCODE(ip)
9715    /* no return */
9716#endif
9717
9718/*
9719 * On entry:
9720 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
9721 */
9722common_selectTrace:
9723    str     r2,[rGLUE,#offGlue_jitState]
9724    mov     r2,#kInterpEntryInstr       @ normal entry reason
9725    str     r2,[rGLUE,#offGlue_entryPoint]
9726    mov     r1,#1                       @ set changeInterp
9727    b       common_gotoBail
9728
9729#if defined(WITH_SELF_VERIFICATION)
9730/*
9731 * Save PC and registers to shadow memory for self verification mode
9732 * before jumping to native translation.
9733 * On entry:
9734 *    rPC, rFP, rGLUE: the values that they should contain
9735 *    r10: the address of the target translation.
9736 */
9737jitSVShadowRunStart:
9738    mov     r0,rPC                      @ r0<- program counter
9739    mov     r1,rFP                      @ r1<- frame pointer
9740    mov     r2,rGLUE                    @ r2<- InterpState pointer
9741    mov     r3,r10                      @ r3<- target translation
9742    bl      dvmSelfVerificationSaveState @ save registers to shadow space
9743    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
9744    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
9745    bx      r10                         @ jump to the translation
9746
9747/*
9748 * Restore PC, registers, and interpState to original values
9749 * before jumping back to the interpreter.
9750 */
9751jitSVShadowRunEnd:
9752    mov    r1,rFP                        @ pass ending fp
9753    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
9754    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
9755    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
9756    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
9757    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
9758    cmp    r1,#0                         @ check for punt condition
9759    beq    1f
9760    mov    r2,#kJitSelfVerification      @ ask for self verification
9761    str    r2,[rGLUE,#offGlue_jitState]
9762    mov    r2,#kInterpEntryInstr         @ normal entry reason
9763    str    r2,[rGLUE,#offGlue_entryPoint]
9764    mov    r1,#1                         @ set changeInterp
9765    b      common_gotoBail
9766
97671:                                       @ exit to interpreter without check
9768    EXPORT_PC()
9769    adrl   rIBASE, dvmAsmInstructionStart
9770    FETCH_INST()
9771    GET_INST_OPCODE(ip)
9772    GOTO_OPCODE(ip)
9773#endif
9774
9775#endif
9776
9777/*
9778 * Common code when a backward branch is taken.
9779 *
9780 * TODO: we could avoid a branch by just setting r0 and falling through
9781 * into the common_periodicChecks code, and having a test on r0 at the
9782 * end determine if we should return to the caller or update & branch to
9783 * the next instr.
9784 *
9785 * On entry:
9786 *  r9 is PC adjustment *in bytes*
9787 */
9788common_backwardBranch:
9789    mov     r0, #kInterpEntryInstr
9790    bl      common_periodicChecks
9791#if defined(WITH_JIT)
9792    GET_JIT_PROF_TABLE(r0)
9793    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9794    cmp     r0,#0
9795    bne     common_updateProfile
9796    GET_INST_OPCODE(ip)
9797    GOTO_OPCODE(ip)
9798#else
9799    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
9800    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9801    GOTO_OPCODE(ip)                     @ jump to next instruction
9802#endif
9803
9804
9805/*
9806 * Need to see if the thread needs to be suspended or debugger/profiler
9807 * activity has begun.  If so, we suspend the thread or side-exit to
9808 * the debug interpreter as appropriate.
9809 *
9810 * The common case is no activity on any of these, so we want to figure
9811 * that out quickly.  If something is up, we can then sort out what.
9812 *
9813 * We want to be fast if the VM was built without debugger or profiler
9814 * support, but we also need to recognize that the system is usually
9815 * shipped with both of these enabled.
9816 *
9817 * TODO: reduce this so we're just checking a single location.
9818 *
9819 * On entry:
9820 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
9821 *  r9 is trampoline PC adjustment *in bytes*
9822 */
9823common_periodicChecks:
9824    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
9825
9826    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9827    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9828
9829    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9830
9831    cmp     r1, #0                      @ debugger enabled?
9832    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9833    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9834    orrnes  ip, ip, r1                  @ ip<- suspendCount | debuggerActive
9835    /*
9836     * Don't switch the interpreter in the libdvm_traceview build even if the
9837     * profiler is active.
9838     * The code here is opted for less intrusion instead of performance.
9839     * That is, *pActiveProfilers is still loaded into r2 even though it is not
9840     * used when WITH_INLINE_PROFILING is defined.
9841     */
9842#if !defined(WITH_INLINE_PROFILING)
9843    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
9844#endif
9845
9846
9847    bxeq    lr                          @ all zero, return
9848
9849    /*
9850     * One or more interesting events have happened.  Figure out what.
9851     *
9852     * If debugging or profiling are compiled in, we need to disambiguate.
9853     *
9854     * r0 still holds the reentry type.
9855     */
9856    ldr     ip, [r3]                    @ ip<- suspendCount (int)
9857    cmp     ip, #0                      @ want suspend?
9858    beq     1f                          @ no, must be debugger/profiler
9859
9860    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
9861#if defined(WITH_JIT)
9862    /*
9863     * Refresh the Jit's cached copy of profile table pointer.  This pointer
9864     * doubles as the Jit's on/off switch.
9865     */
9866    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
9867    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9868    ldr     r3, [r3] @ r3 <- pJitProfTable
9869    EXPORT_PC()                         @ need for precise GC
9870    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
9871#else
9872    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
9873    EXPORT_PC()                         @ need for precise GC
9874#endif
9875    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
9876    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
9877
9878    /*
9879     * Reload the debugger/profiler enable flags.  We're checking to see
9880     * if either of these got set while we were suspended.
9881     *
9882     * If WITH_INLINE_PROFILING is configured, don't check whether the profiler
9883     * is enabled or not as the profiling will be done inline.
9884     */
9885    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
9886    cmp     r1, #0                      @ debugger enabled?
9887    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
9888
9889#if !defined(WITH_INLINE_PROFILING)
9890    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
9891    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
9892    orrs    r1, r1, r2
9893#else
9894    cmp     r1, #0                      @ only consult the debuggerActive flag
9895#endif
9896
9897    beq     2f
9898
98991:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
9900    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
9901    add     rPC, rPC, r9                @ update rPC
9902    mov     r1, #1                      @ "want switch" = true
9903    b       common_gotoBail             @ side exit
9904
99052:
9906    bx      lr                          @ nothing to do, return
9907
9908
9909/*
9910 * The equivalent of "goto bail", this calls through the "bail handler".
9911 *
9912 * State registers will be saved to the "glue" area before bailing.
9913 *
9914 * On entry:
9915 *  r1 is "bool changeInterp", indicating if we want to switch to the
9916 *     other interpreter or just bail all the way out
9917 */
9918common_gotoBail:
9919    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
9920    mov     r0, rGLUE                   @ r0<- glue ptr
9921    b       dvmMterpStdBail             @ call(glue, changeInterp)
9922
9923    @add     r1, r1, #1                  @ using (boolean+1)
9924    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
9925    @bl      _longjmp                    @ does not return
9926    @bl      common_abort
9927
9928
9929/*
9930 * Common code for method invocation with range.
9931 *
9932 * On entry:
9933 *  r0 is "Method* methodToCall", the method we're trying to call
9934 */
9935common_invokeMethodRange:
9936.LinvokeNewRange:
9937    @ prepare to copy args to "outs" area of current frame
9938    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
9939    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9940    beq     .LinvokeArgsDone            @ if no args, skip the rest
9941    FETCH(r1, 2)                        @ r1<- CCCC
9942
9943    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
9944    @ (very few methods have > 10 args; could unroll for common cases)
9945    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
9946    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
9947    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
99481:  ldr     r1, [r3], #4                @ val = *fp++
9949    subs    r2, r2, #1                  @ count--
9950    str     r1, [r10], #4               @ *outs++ = val
9951    bne     1b                          @ ...while count != 0
9952    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
9953    b       .LinvokeArgsDone
9954
9955/*
9956 * Common code for method invocation without range.
9957 *
9958 * On entry:
9959 *  r0 is "Method* methodToCall", the method we're trying to call
9960 */
9961common_invokeMethodNoRange:
9962.LinvokeNewNoRange:
9963    @ prepare to copy args to "outs" area of current frame
9964    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
9965    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
9966    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
9967    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
9968    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
9969    beq     .LinvokeArgsDone
9970
9971    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
9972.LinvokeNonRange:
9973    rsb     r2, r2, #5                  @ r2<- 5-r2
9974    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
9975    bl      common_abort                @ (skipped due to ARM prefetch)
99765:  and     ip, rINST, #0x0f00          @ isolate A
9977    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
9978    mov     r0, r0                      @ nop
9979    str     r2, [r10, #-4]!             @ *--outs = vA
99804:  and     ip, r1, #0xf000             @ isolate G
9981    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
9982    mov     r0, r0                      @ nop
9983    str     r2, [r10, #-4]!             @ *--outs = vG
99843:  and     ip, r1, #0x0f00             @ isolate F
9985    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
9986    mov     r0, r0                      @ nop
9987    str     r2, [r10, #-4]!             @ *--outs = vF
99882:  and     ip, r1, #0x00f0             @ isolate E
9989    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
9990    mov     r0, r0                      @ nop
9991    str     r2, [r10, #-4]!             @ *--outs = vE
99921:  and     ip, r1, #0x000f             @ isolate D
9993    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
9994    mov     r0, r0                      @ nop
9995    str     r2, [r10, #-4]!             @ *--outs = vD
99960:  @ fall through to .LinvokeArgsDone
9997
9998.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
9999    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
10000    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
10001    @ find space for the new stack frame, check for overflow
10002    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
10003    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
10004    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
10005@    bl      common_dumpRegs
10006    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
10007    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
10008    cmp     r3, r9                      @ bottom < interpStackEnd?
10009    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
10010    blo     .LstackOverflow             @ yes, this frame will overflow stack
10011
10012    @ set up newSaveArea
10013#ifdef EASY_GDB
10014    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
10015    str     ip, [r10, #offStackSaveArea_prevSave]
10016#endif
10017    str     rFP, [r10, #offStackSaveArea_prevFrame]
10018    str     rPC, [r10, #offStackSaveArea_savedPc]
10019#if defined(WITH_JIT)
10020    mov     r9, #0
10021    str     r9, [r10, #offStackSaveArea_returnAddr]
10022#endif
10023#if defined(WITH_INLINE_PROFILING)
10024    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10025    mov     r1, r6
10026    @ r0=methodToCall, r1=rGlue
10027    bl      dvmFastMethodTraceEnter
10028    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10029#endif
10030    str     r0, [r10, #offStackSaveArea_method]
10031    tst     r3, #ACC_NATIVE
10032    bne     .LinvokeNative
10033
10034    /*
10035    stmfd   sp!, {r0-r3}
10036    bl      common_printNewline
10037    mov     r0, rFP
10038    mov     r1, #0
10039    bl      dvmDumpFp
10040    ldmfd   sp!, {r0-r3}
10041    stmfd   sp!, {r0-r3}
10042    mov     r0, r1
10043    mov     r1, r10
10044    bl      dvmDumpFp
10045    bl      common_printNewline
10046    ldmfd   sp!, {r0-r3}
10047    */
10048
10049    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10050    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10051    mov     rPC, r2                         @ publish new rPC
10052    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10053
10054    @ Update "glue" values for the new method
10055    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10056    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10057    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10058#if defined(WITH_JIT)
10059    GET_JIT_PROF_TABLE(r0)
10060    mov     rFP, r1                         @ fp = newFp
10061    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10062    mov     rINST, r9                       @ publish new rINST
10063    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10064    cmp     r0,#0
10065    bne     common_updateProfile
10066    GOTO_OPCODE(ip)                         @ jump to next instruction
10067#else
10068    mov     rFP, r1                         @ fp = newFp
10069    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10070    mov     rINST, r9                       @ publish new rINST
10071    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10072    GOTO_OPCODE(ip)                         @ jump to next instruction
10073#endif
10074
10075.LinvokeNative:
10076    @ Prep for the native call
10077    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10078    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10079    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10080    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10081    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10082    mov     r9, r3                      @ r9<- glue->self (preserve)
10083
10084    mov     r2, r0                      @ r2<- methodToCall
10085    mov     r0, r1                      @ r0<- newFp (points to args)
10086    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10087
10088#ifdef ASSIST_DEBUGGER
10089    /* insert fake function header to help gdb find the stack frame */
10090    b       .Lskip
10091    .type   dalvik_mterp, %function
10092dalvik_mterp:
10093    .fnstart
10094    MTERP_ENTRY1
10095    MTERP_ENTRY2
10096.Lskip:
10097#endif
10098
10099#if defined(WITH_INLINE_PROFILING)
10100    @ r2=JNIMethod, r6=rGLUE
10101    stmfd   sp!, {r2,r6}
10102#endif
10103
10104    @mov     lr, pc                      @ set return addr
10105    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10106    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10107
10108#if defined(WITH_INLINE_PROFILING)
10109    @ r0=JNIMethod, r1=rGLUE
10110    ldmfd   sp!, {r0-r1}
10111    bl      dvmFastNativeMethodTraceExit
10112#endif
10113
10114#if defined(WITH_JIT)
10115    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10116#endif
10117
10118    @ native return; r9=self, r10=newSaveArea
10119    @ equivalent to dvmPopJniLocals
10120    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10121    ldr     r1, [r9, #offThread_exception] @ check for exception
10122#if defined(WITH_JIT)
10123    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10124#endif
10125    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10126    cmp     r1, #0                      @ null?
10127    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10128#if defined(WITH_JIT)
10129    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10130#endif
10131    bne     common_exceptionThrown      @ no, handle exception
10132
10133    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10134    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10135    GOTO_OPCODE(ip)                     @ jump to next instruction
10136
10137.LstackOverflow:    @ r0=methodToCall
10138    mov     r1, r0                      @ r1<- methodToCall
10139    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10140    bl      dvmHandleStackOverflow
10141    b       common_exceptionThrown
10142#ifdef ASSIST_DEBUGGER
10143    .fnend
10144#endif
10145
10146
10147    /*
10148     * Common code for method invocation, calling through "glue code".
10149     *
10150     * TODO: now that we have range and non-range invoke handlers, this
10151     *       needs to be split into two.  Maybe just create entry points
10152     *       that set r9 and jump here?
10153     *
10154     * On entry:
10155     *  r0 is "Method* methodToCall", the method we're trying to call
10156     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10157     */
10158     .if    0
10159.LinvokeOld:
10160    sub     sp, sp, #8                  @ space for args + pad
10161    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10162    mov     r2, r0                      @ A2<- methodToCall
10163    mov     r0, rGLUE                   @ A0<- glue
10164    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10165    mov     r1, r9                      @ A1<- methodCallRange
10166    mov     r3, rINST, lsr #8           @ A3<- AA
10167    str     ip, [sp, #0]                @ A4<- ip
10168    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10169    add     sp, sp, #8                  @ remove arg area
10170    b       common_resumeAfterGlueCall  @ continue to next instruction
10171    .endif
10172
10173
10174
10175/*
10176 * Common code for handling a return instruction.
10177 *
10178 * This does not return.
10179 */
10180common_returnFromMethod:
10181.LreturnNew:
10182    mov     r0, #kInterpEntryReturn
10183    mov     r9, #0
10184    bl      common_periodicChecks
10185
10186#if defined(WITH_INLINE_PROFILING)
10187    stmfd   sp!, {r0-r3}                @ preserve r0-r3
10188    mov     r0, r6
10189    @ r0=rGlue
10190    bl      dvmFastJavaMethodTraceExit
10191    ldmfd   sp!, {r0-r3}                @ restore r0-r3
10192#endif
10193    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10194    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10195    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10196    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10197                                        @ r2<- method we're returning to
10198    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10199    cmp     r2, #0                      @ is this a break frame?
10200    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10201    mov     r1, #0                      @ "want switch" = false
10202    beq     common_gotoBail             @ break frame, bail out completely
10203
10204    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10205    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10206    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10207    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10208#if defined(WITH_JIT)
10209    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10210    mov     rPC, r9                     @ publish new rPC
10211    str     r1, [rGLUE, #offGlue_methodClassDex]
10212    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10213    cmp     r10, #0                      @ caller is compiled code
10214    blxne   r10
10215    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10216    GOTO_OPCODE(ip)                     @ jump to next instruction
10217#else
10218    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10219    mov     rPC, r9                     @ publish new rPC
10220    str     r1, [rGLUE, #offGlue_methodClassDex]
10221    GOTO_OPCODE(ip)                     @ jump to next instruction
10222#endif
10223
10224    /*
10225     * Return handling, calls through "glue code".
10226     */
10227     .if    0
10228.LreturnOld:
10229    SAVE_PC_FP_TO_GLUE()                @ export state
10230    mov     r0, rGLUE                   @ arg to function
10231    bl      dvmMterp_returnFromMethod
10232    b       common_resumeAfterGlueCall
10233    .endif
10234
10235
10236/*
10237 * Somebody has thrown an exception.  Handle it.
10238 *
10239 * If the exception processing code returns to us (instead of falling
10240 * out of the interpreter), continue with whatever the next instruction
10241 * now happens to be.
10242 *
10243 * This does not return.
10244 */
10245     .global dvmMterpCommonExceptionThrown
10246dvmMterpCommonExceptionThrown:
10247common_exceptionThrown:
10248.LexceptionNew:
10249    mov     r0, #kInterpEntryThrow
10250    mov     r9, #0
10251    bl      common_periodicChecks
10252
10253    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10254    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10255    mov     r1, r10                     @ r1<- self
10256    mov     r0, r9                      @ r0<- exception
10257    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10258    mov     r3, #0                      @ r3<- NULL
10259    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10260
10261    /* set up args and a local for "&fp" */
10262    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10263    str     rFP, [sp, #-4]!             @ *--sp = fp
10264    mov     ip, sp                      @ ip<- &fp
10265    mov     r3, #0                      @ r3<- false
10266    str     ip, [sp, #-4]!              @ *--sp = &fp
10267    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10268    mov     r0, r10                     @ r0<- self
10269    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10270    mov     r2, r9                      @ r2<- exception
10271    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10272    mov     r1, r1, asr #1              @ r1<- offset in code units
10273
10274    /* call, r0 gets catchRelPc (a code-unit offset) */
10275    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10276
10277    /* fix earlier stack overflow if necessary; may trash rFP */
10278    ldrb    r1, [r10, #offThread_stackOverflowed]
10279    cmp     r1, #0                      @ did we overflow earlier?
10280    beq     1f                          @ no, skip ahead
10281    mov     rFP, r0                     @ save relPc result in rFP
10282    mov     r0, r10                     @ r0<- self
10283    mov     r1, r9                      @ r1<- exception
10284    bl      dvmCleanupStackOverflow     @ call(self)
10285    mov     r0, rFP                     @ restore result
102861:
10287
10288    /* update frame pointer and check result from dvmFindCatchBlock */
10289    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10290    cmp     r0, #0                      @ is catchRelPc < 0?
10291    add     sp, sp, #8                  @ restore stack
10292    bmi     .LnotCaughtLocally
10293
10294    /* adjust locals to match self->curFrame and updated PC */
10295    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10296    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10297    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10298    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10299    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10300    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10301    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10302    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10303
10304    /* release the tracked alloc on the exception */
10305    mov     r0, r9                      @ r0<- exception
10306    mov     r1, r10                     @ r1<- self
10307    bl      dvmReleaseTrackedAlloc      @ release the exception
10308
10309    /* restore the exception if the handler wants it */
10310    FETCH_INST()                        @ load rINST from rPC
10311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10312    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10313    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10314    GOTO_OPCODE(ip)                     @ jump to next instruction
10315
10316.LnotCaughtLocally: @ r9=exception, r10=self
10317    /* fix stack overflow if necessary */
10318    ldrb    r1, [r10, #offThread_stackOverflowed]
10319    cmp     r1, #0                      @ did we overflow earlier?
10320    movne   r0, r10                     @ if yes: r0<- self
10321    movne   r1, r9                      @ if yes: r1<- exception
10322    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10323
10324    @ may want to show "not caught locally" debug messages here
10325#if DVM_SHOW_EXCEPTION >= 2
10326    /* call __android_log_print(prio, tag, format, ...) */
10327    /* "Exception %s from %s:%d not caught locally" */
10328    @ dvmLineNumFromPC(method, pc - method->insns)
10329    ldr     r0, [rGLUE, #offGlue_method]
10330    ldr     r1, [r0, #offMethod_insns]
10331    sub     r1, rPC, r1
10332    asr     r1, r1, #1
10333    bl      dvmLineNumFromPC
10334    str     r0, [sp, #-4]!
10335    @ dvmGetMethodSourceFile(method)
10336    ldr     r0, [rGLUE, #offGlue_method]
10337    bl      dvmGetMethodSourceFile
10338    str     r0, [sp, #-4]!
10339    @ exception->clazz->descriptor
10340    ldr     r3, [r9, #offObject_clazz]
10341    ldr     r3, [r3, #offClassObject_descriptor]
10342    @
10343    ldr     r2, strExceptionNotCaughtLocally
10344    ldr     r1, strLogTag
10345    mov     r0, #3                      @ LOG_DEBUG
10346    bl      __android_log_print
10347#endif
10348    str     r9, [r10, #offThread_exception] @ restore exception
10349    mov     r0, r9                      @ r0<- exception
10350    mov     r1, r10                     @ r1<- self
10351    bl      dvmReleaseTrackedAlloc      @ release the exception
10352    mov     r1, #0                      @ "want switch" = false
10353    b       common_gotoBail             @ bail out
10354
10355
10356    /*
10357     * Exception handling, calls through "glue code".
10358     */
10359    .if     0
10360.LexceptionOld:
10361    SAVE_PC_FP_TO_GLUE()                @ export state
10362    mov     r0, rGLUE                   @ arg to function
10363    bl      dvmMterp_exceptionThrown
10364    b       common_resumeAfterGlueCall
10365    .endif
10366
10367
10368/*
10369 * After returning from a "glued" function, pull out the updated
10370 * values and start executing at the next instruction.
10371 */
10372common_resumeAfterGlueCall:
10373    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10374    FETCH_INST()                        @ load rINST from rPC
10375    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10376    GOTO_OPCODE(ip)                     @ jump to next instruction
10377
10378/*
10379 * Invalid array index.
10380 */
10381common_errArrayIndex:
10382    EXPORT_PC()
10383    ldr     r0, strArrayIndexException
10384    mov     r1, #0
10385    bl      dvmThrowException
10386    b       common_exceptionThrown
10387
10388/*
10389 * Invalid array value.
10390 */
10391common_errArrayStore:
10392    EXPORT_PC()
10393    ldr     r0, strArrayStoreException
10394    mov     r1, #0
10395    bl      dvmThrowException
10396    b       common_exceptionThrown
10397
10398/*
10399 * Integer divide or mod by zero.
10400 */
10401common_errDivideByZero:
10402    EXPORT_PC()
10403    ldr     r0, strArithmeticException
10404    ldr     r1, strDivideByZero
10405    bl      dvmThrowException
10406    b       common_exceptionThrown
10407
10408/*
10409 * Attempt to allocate an array with a negative size.
10410 */
10411common_errNegativeArraySize:
10412    EXPORT_PC()
10413    ldr     r0, strNegativeArraySizeException
10414    mov     r1, #0
10415    bl      dvmThrowException
10416    b       common_exceptionThrown
10417
10418/*
10419 * Invocation of a non-existent method.
10420 */
10421common_errNoSuchMethod:
10422    EXPORT_PC()
10423    ldr     r0, strNoSuchMethodError
10424    mov     r1, #0
10425    bl      dvmThrowException
10426    b       common_exceptionThrown
10427
10428/*
10429 * We encountered a null object when we weren't expecting one.  We
10430 * export the PC, throw a NullPointerException, and goto the exception
10431 * processing code.
10432 */
10433common_errNullObject:
10434    EXPORT_PC()
10435    ldr     r0, strNullPointerException
10436    mov     r1, #0
10437    bl      dvmThrowException
10438    b       common_exceptionThrown
10439
10440/*
10441 * For debugging, cause an immediate fault.  The source address will
10442 * be in lr (use a bl instruction to jump here).
10443 */
10444common_abort:
10445    ldr     pc, .LdeadFood
10446.LdeadFood:
10447    .word   0xdeadf00d
10448
10449/*
10450 * Spit out a "we were here", preserving all registers.  (The attempt
10451 * to save ip won't work, but we need to save an even number of
10452 * registers for EABI 64-bit stack alignment.)
10453 */
10454    .macro  SQUEAK num
10455common_squeak\num:
10456    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10457    ldr     r0, strSqueak
10458    mov     r1, #\num
10459    bl      printf
10460    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10461    bx      lr
10462    .endm
10463
10464    SQUEAK  0
10465    SQUEAK  1
10466    SQUEAK  2
10467    SQUEAK  3
10468    SQUEAK  4
10469    SQUEAK  5
10470
10471/*
10472 * Spit out the number in r0, preserving registers.
10473 */
10474common_printNum:
10475    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10476    mov     r1, r0
10477    ldr     r0, strSqueak
10478    bl      printf
10479    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10480    bx      lr
10481
10482/*
10483 * Print a newline, preserving registers.
10484 */
10485common_printNewline:
10486    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10487    ldr     r0, strNewline
10488    bl      printf
10489    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10490    bx      lr
10491
10492    /*
10493     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10494     */
10495common_printHex:
10496    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10497    mov     r1, r0
10498    ldr     r0, strPrintHex
10499    bl      printf
10500    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10501    bx      lr
10502
10503/*
10504 * Print the 64-bit quantity in r0-r1, preserving registers.
10505 */
10506common_printLong:
10507    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10508    mov     r3, r1
10509    mov     r2, r0
10510    ldr     r0, strPrintLong
10511    bl      printf
10512    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10513    bx      lr
10514
10515/*
10516 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10517 */
10518common_printMethod:
10519    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10520    bl      dvmMterpPrintMethod
10521    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10522    bx      lr
10523
10524/*
10525 * Call a C helper function that dumps regs and possibly some
10526 * additional info.  Requires the C function to be compiled in.
10527 */
10528    .if     0
10529common_dumpRegs:
10530    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10531    bl      dvmMterpDumpArmRegs
10532    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10533    bx      lr
10534    .endif
10535
10536#if 0
10537/*
10538 * Experiment on VFP mode.
10539 *
10540 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10541 *
10542 * Updates the bits specified by "mask", setting them to the values in "val".
10543 */
10544setFPSCR:
10545    and     r0, r0, r1                  @ make sure no stray bits are set
10546    fmrx    r2, fpscr                   @ get VFP reg
10547    mvn     r1, r1                      @ bit-invert mask
10548    and     r2, r2, r1                  @ clear masked bits
10549    orr     r2, r2, r0                  @ set specified bits
10550    fmxr    fpscr, r2                   @ set VFP reg
10551    mov     r0, r2                      @ return new value
10552    bx      lr
10553
10554    .align  2
10555    .global dvmConfigureFP
10556    .type   dvmConfigureFP, %function
10557dvmConfigureFP:
10558    stmfd   sp!, {ip, lr}
10559    /* 0x03000000 sets DN/FZ */
10560    /* 0x00009f00 clears the six exception enable flags */
10561    bl      common_squeak0
10562    mov     r0, #0x03000000             @ r0<- 0x03000000
10563    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10564    bl      setFPSCR
10565    ldmfd   sp!, {ip, pc}
10566#endif
10567
10568
10569/*
10570 * String references, must be close to the code that uses them.
10571 */
10572    .align  2
10573strArithmeticException:
10574    .word   .LstrArithmeticException
10575strArrayIndexException:
10576    .word   .LstrArrayIndexException
10577strArrayStoreException:
10578    .word   .LstrArrayStoreException
10579strDivideByZero:
10580    .word   .LstrDivideByZero
10581strNegativeArraySizeException:
10582    .word   .LstrNegativeArraySizeException
10583strNoSuchMethodError:
10584    .word   .LstrNoSuchMethodError
10585strNullPointerException:
10586    .word   .LstrNullPointerException
10587
10588strLogTag:
10589    .word   .LstrLogTag
10590strExceptionNotCaughtLocally:
10591    .word   .LstrExceptionNotCaughtLocally
10592
10593strNewline:
10594    .word   .LstrNewline
10595strSqueak:
10596    .word   .LstrSqueak
10597strPrintHex:
10598    .word   .LstrPrintHex
10599strPrintLong:
10600    .word   .LstrPrintLong
10601
10602/*
10603 * Zero-terminated ASCII string data.
10604 *
10605 * On ARM we have two choices: do like gcc does, and LDR from a .word
10606 * with the address, or use an ADR pseudo-op to get the address
10607 * directly.  ADR saves 4 bytes and an indirection, but it's using a
10608 * PC-relative addressing mode and hence has a limited range, which
10609 * makes it not work well with mergeable string sections.
10610 */
10611    .section .rodata.str1.4,"aMS",%progbits,1
10612
10613.LstrBadEntryPoint:
10614    .asciz  "Bad entry point %d\n"
10615.LstrArithmeticException:
10616    .asciz  "Ljava/lang/ArithmeticException;"
10617.LstrArrayIndexException:
10618    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
10619.LstrArrayStoreException:
10620    .asciz  "Ljava/lang/ArrayStoreException;"
10621.LstrClassCastException:
10622    .asciz  "Ljava/lang/ClassCastException;"
10623.LstrDivideByZero:
10624    .asciz  "divide by zero"
10625.LstrFilledNewArrayNotImpl:
10626    .asciz  "filled-new-array only implemented for objects and 'int'"
10627.LstrInternalError:
10628    .asciz  "Ljava/lang/InternalError;"
10629.LstrInstantiationError:
10630    .asciz  "Ljava/lang/InstantiationError;"
10631.LstrNegativeArraySizeException:
10632    .asciz  "Ljava/lang/NegativeArraySizeException;"
10633.LstrNoSuchMethodError:
10634    .asciz  "Ljava/lang/NoSuchMethodError;"
10635.LstrNullPointerException:
10636    .asciz  "Ljava/lang/NullPointerException;"
10637
10638.LstrLogTag:
10639    .asciz  "mterp"
10640.LstrExceptionNotCaughtLocally:
10641    .asciz  "Exception %s from %s:%d not caught locally\n"
10642
10643.LstrNewline:
10644    .asciz  "\n"
10645.LstrSqueak:
10646    .asciz  "<%d>"
10647.LstrPrintHex:
10648    .asciz  "<0x%x>"
10649.LstrPrintLong:
10650    .asciz  "<%lld>"
10651
10652