1/*
2 * This file was generated automatically by gen-mterp.py for 'armv4t'.
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: armv5te/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     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1309     * on what value we'd like to return when one of the operands is NaN.
1310     *
1311     * The operation we're implementing is:
1312     *   if (x == y)
1313     *     return 0;
1314     *   else if (x < y)
1315     *     return -1;
1316     *   else if (x > y)
1317     *     return 1;
1318     *   else
1319     *     return {-1,1};  // one or both operands was NaN
1320     *
1321     * The straightforward implementation requires 3 calls to functions
1322     * that return a result in r0.  We can do it with two calls if our
1323     * EABI library supports __aeabi_cfcmple (only one if we want to check
1324     * for NaN directly):
1325     *   check x <= y
1326     *     if <, return -1
1327     *     if ==, return 0
1328     *   check y <= x
1329     *     if <, return 1
1330     *   return {-1,1}
1331     *
1332     * for: cmpl-float, cmpg-float
1333     */
1334    /* op vAA, vBB, vCC */
1335    FETCH(r0, 1)                        @ r0<- CCBB
1336    and     r2, r0, #255                @ r2<- BB
1337    mov     r3, r0, lsr #8              @ r3<- CC
1338    GET_VREG(r9, r2)                    @ r9<- vBB
1339    GET_VREG(r10, r3)                   @ r10<- vCC
1340    mov     r0, r9                      @ copy to arg registers
1341    mov     r1, r10
1342    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1343    bhi     .LOP_CMPL_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1344    mvncc   r1, #0                      @ (less than) r1<- -1
1345    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1346.LOP_CMPL_FLOAT_finish:
1347    mov     r3, rINST, lsr #8           @ r3<- AA
1348    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1349    SET_VREG(r1, r3)                    @ vAA<- r1
1350    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1351    GOTO_OPCODE(ip)                     @ jump to next instruction
1352
1353/* ------------------------------ */
1354    .balign 64
1355.L_OP_CMPG_FLOAT: /* 0x2e */
1356/* File: armv5te/OP_CMPG_FLOAT.S */
1357/* File: armv5te/OP_CMPL_FLOAT.S */
1358    /*
1359     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1360     * destination register based on the results of the comparison.
1361     *
1362     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1363     * on what value we'd like to return when one of the operands is NaN.
1364     *
1365     * The operation we're implementing is:
1366     *   if (x == y)
1367     *     return 0;
1368     *   else if (x < y)
1369     *     return -1;
1370     *   else if (x > y)
1371     *     return 1;
1372     *   else
1373     *     return {-1,1};  // one or both operands was NaN
1374     *
1375     * The straightforward implementation requires 3 calls to functions
1376     * that return a result in r0.  We can do it with two calls if our
1377     * EABI library supports __aeabi_cfcmple (only one if we want to check
1378     * for NaN directly):
1379     *   check x <= y
1380     *     if <, return -1
1381     *     if ==, return 0
1382     *   check y <= x
1383     *     if <, return 1
1384     *   return {-1,1}
1385     *
1386     * for: cmpl-float, cmpg-float
1387     */
1388    /* op vAA, vBB, vCC */
1389    FETCH(r0, 1)                        @ r0<- CCBB
1390    and     r2, r0, #255                @ r2<- BB
1391    mov     r3, r0, lsr #8              @ r3<- CC
1392    GET_VREG(r9, r2)                    @ r9<- vBB
1393    GET_VREG(r10, r3)                   @ r10<- vCC
1394    mov     r0, r9                      @ copy to arg registers
1395    mov     r1, r10
1396    bl      __aeabi_cfcmple             @ cmp <=: C clear if <, Z set if eq
1397    bhi     .LOP_CMPG_FLOAT_gt_or_nan       @ C set and Z clear, disambiguate
1398    mvncc   r1, #0                      @ (less than) r1<- -1
1399    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1400.LOP_CMPG_FLOAT_finish:
1401    mov     r3, rINST, lsr #8           @ r3<- AA
1402    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1403    SET_VREG(r1, r3)                    @ vAA<- r1
1404    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1405    GOTO_OPCODE(ip)                     @ jump to next instruction
1406
1407
1408/* ------------------------------ */
1409    .balign 64
1410.L_OP_CMPL_DOUBLE: /* 0x2f */
1411/* File: armv5te/OP_CMPL_DOUBLE.S */
1412    /*
1413     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1414     * destination register based on the results of the comparison.
1415     *
1416     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1417     * on what value we'd like to return when one of the operands is NaN.
1418     *
1419     * See OP_CMPL_FLOAT for an explanation.
1420     *
1421     * For: cmpl-double, cmpg-double
1422     */
1423    /* op vAA, vBB, vCC */
1424    FETCH(r0, 1)                        @ r0<- CCBB
1425    and     r9, r0, #255                @ r9<- BB
1426    mov     r10, r0, lsr #8             @ r10<- CC
1427    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1428    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1429    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1430    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1431    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1432    bhi     .LOP_CMPL_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1433    mvncc   r1, #0                      @ (less than) r1<- -1
1434    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1435.LOP_CMPL_DOUBLE_finish:
1436    mov     r3, rINST, lsr #8           @ r3<- AA
1437    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1438    SET_VREG(r1, r3)                    @ vAA<- r1
1439    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1440    GOTO_OPCODE(ip)                     @ jump to next instruction
1441
1442/* ------------------------------ */
1443    .balign 64
1444.L_OP_CMPG_DOUBLE: /* 0x30 */
1445/* File: armv5te/OP_CMPG_DOUBLE.S */
1446/* File: armv5te/OP_CMPL_DOUBLE.S */
1447    /*
1448     * Compare two floating-point values.  Puts 0, 1, or -1 into the
1449     * destination register based on the results of the comparison.
1450     *
1451     * Provide a "naninst" instruction that puts 1 or -1 into r1 depending
1452     * on what value we'd like to return when one of the operands is NaN.
1453     *
1454     * See OP_CMPL_FLOAT for an explanation.
1455     *
1456     * For: cmpl-double, cmpg-double
1457     */
1458    /* op vAA, vBB, vCC */
1459    FETCH(r0, 1)                        @ r0<- CCBB
1460    and     r9, r0, #255                @ r9<- BB
1461    mov     r10, r0, lsr #8             @ r10<- CC
1462    add     r9, rFP, r9, lsl #2         @ r9<- &fp[BB]
1463    add     r10, rFP, r10, lsl #2       @ r10<- &fp[CC]
1464    ldmia   r9, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1465    ldmia   r10, {r2-r3}                @ r2/r3<- vCC/vCC+1
1466    bl      __aeabi_cdcmple             @ cmp <=: C clear if <, Z set if eq
1467    bhi     .LOP_CMPG_DOUBLE_gt_or_nan       @ C set and Z clear, disambiguate
1468    mvncc   r1, #0                      @ (less than) r1<- -1
1469    moveq   r1, #0                      @ (equal) r1<- 0, trumps less than
1470.LOP_CMPG_DOUBLE_finish:
1471    mov     r3, rINST, lsr #8           @ r3<- AA
1472    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
1473    SET_VREG(r1, r3)                    @ vAA<- r1
1474    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1475    GOTO_OPCODE(ip)                     @ jump to next instruction
1476
1477
1478/* ------------------------------ */
1479    .balign 64
1480.L_OP_CMP_LONG: /* 0x31 */
1481/* File: armv5te/OP_CMP_LONG.S */
1482    /*
1483     * Compare two 64-bit values.  Puts 0, 1, or -1 into the destination
1484     * register based on the results of the comparison.
1485     *
1486     * We load the full values with LDM, but in practice many values could
1487     * be resolved by only looking at the high word.  This could be made
1488     * faster or slower by splitting the LDM into a pair of LDRs.
1489     *
1490     * If we just wanted to set condition flags, we could do this:
1491     *  subs    ip, r0, r2
1492     *  sbcs    ip, r1, r3
1493     *  subeqs  ip, r0, r2
1494     * Leaving { <0, 0, >0 } in ip.  However, we have to set it to a specific
1495     * integer value, which we can do with 2 conditional mov/mvn instructions
1496     * (set 1, set -1; if they're equal we already have 0 in ip), giving
1497     * us a constant 5-cycle path plus a branch at the end to the
1498     * instruction epilogue code.  The multi-compare approach below needs
1499     * 2 or 3 cycles + branch if the high word doesn't match, 6 + branch
1500     * in the worst case (the 64-bit values are equal).
1501     */
1502    /* cmp-long vAA, vBB, vCC */
1503    FETCH(r0, 1)                        @ r0<- CCBB
1504    mov     r9, rINST, lsr #8           @ r9<- AA
1505    and     r2, r0, #255                @ r2<- BB
1506    mov     r3, r0, lsr #8              @ r3<- CC
1507    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
1508    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
1509    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
1510    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
1511    cmp     r1, r3                      @ compare (vBB+1, vCC+1)
1512    blt     .LOP_CMP_LONG_less            @ signed compare on high part
1513    bgt     .LOP_CMP_LONG_greater
1514    subs    r1, r0, r2                  @ r1<- r0 - r2
1515    bhi     .LOP_CMP_LONG_greater         @ unsigned compare on low part
1516    bne     .LOP_CMP_LONG_less
1517    b       .LOP_CMP_LONG_finish          @ equal; r1 already holds 0
1518
1519/* ------------------------------ */
1520    .balign 64
1521.L_OP_IF_EQ: /* 0x32 */
1522/* File: armv5te/OP_IF_EQ.S */
1523/* File: armv5te/bincmp.S */
1524    /*
1525     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1526     * fragment that specifies the *reverse* comparison to perform, e.g.
1527     * for "if-le" you would use "gt".
1528     *
1529     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1530     */
1531    /* if-cmp vA, vB, +CCCC */
1532    mov     r0, rINST, lsr #8           @ r0<- A+
1533    mov     r1, rINST, lsr #12          @ r1<- B
1534    and     r0, r0, #15
1535    GET_VREG(r3, r1)                    @ r3<- vB
1536    GET_VREG(r2, r0)                    @ r2<- vA
1537    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1538    cmp     r2, r3                      @ compare (vA, vB)
1539    bne  1f                      @ branch to 1 if comparison failed
1540    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1541    movs    r9, r9, asl #1              @ convert to bytes, check sign
1542    bmi     common_backwardBranch       @ yes, do periodic checks
15431:
1544#if defined(WITH_JIT)
1545    GET_JIT_PROF_TABLE(r0)
1546    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1547    b        common_testUpdateProfile
1548#else
1549    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1550    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1551    GOTO_OPCODE(ip)                     @ jump to next instruction
1552#endif
1553
1554
1555/* ------------------------------ */
1556    .balign 64
1557.L_OP_IF_NE: /* 0x33 */
1558/* File: armv5te/OP_IF_NE.S */
1559/* File: armv5te/bincmp.S */
1560    /*
1561     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1562     * fragment that specifies the *reverse* comparison to perform, e.g.
1563     * for "if-le" you would use "gt".
1564     *
1565     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1566     */
1567    /* if-cmp vA, vB, +CCCC */
1568    mov     r0, rINST, lsr #8           @ r0<- A+
1569    mov     r1, rINST, lsr #12          @ r1<- B
1570    and     r0, r0, #15
1571    GET_VREG(r3, r1)                    @ r3<- vB
1572    GET_VREG(r2, r0)                    @ r2<- vA
1573    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1574    cmp     r2, r3                      @ compare (vA, vB)
1575    beq  1f                      @ branch to 1 if comparison failed
1576    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1577    movs    r9, r9, asl #1              @ convert to bytes, check sign
1578    bmi     common_backwardBranch       @ yes, do periodic checks
15791:
1580#if defined(WITH_JIT)
1581    GET_JIT_PROF_TABLE(r0)
1582    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1583    b        common_testUpdateProfile
1584#else
1585    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1587    GOTO_OPCODE(ip)                     @ jump to next instruction
1588#endif
1589
1590
1591/* ------------------------------ */
1592    .balign 64
1593.L_OP_IF_LT: /* 0x34 */
1594/* File: armv5te/OP_IF_LT.S */
1595/* File: armv5te/bincmp.S */
1596    /*
1597     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1598     * fragment that specifies the *reverse* comparison to perform, e.g.
1599     * for "if-le" you would use "gt".
1600     *
1601     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1602     */
1603    /* if-cmp vA, vB, +CCCC */
1604    mov     r0, rINST, lsr #8           @ r0<- A+
1605    mov     r1, rINST, lsr #12          @ r1<- B
1606    and     r0, r0, #15
1607    GET_VREG(r3, r1)                    @ r3<- vB
1608    GET_VREG(r2, r0)                    @ r2<- vA
1609    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1610    cmp     r2, r3                      @ compare (vA, vB)
1611    bge  1f                      @ branch to 1 if comparison failed
1612    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1613    movs    r9, r9, asl #1              @ convert to bytes, check sign
1614    bmi     common_backwardBranch       @ yes, do periodic checks
16151:
1616#if defined(WITH_JIT)
1617    GET_JIT_PROF_TABLE(r0)
1618    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1619    b        common_testUpdateProfile
1620#else
1621    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1622    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1623    GOTO_OPCODE(ip)                     @ jump to next instruction
1624#endif
1625
1626
1627/* ------------------------------ */
1628    .balign 64
1629.L_OP_IF_GE: /* 0x35 */
1630/* File: armv5te/OP_IF_GE.S */
1631/* File: armv5te/bincmp.S */
1632    /*
1633     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1634     * fragment that specifies the *reverse* comparison to perform, e.g.
1635     * for "if-le" you would use "gt".
1636     *
1637     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1638     */
1639    /* if-cmp vA, vB, +CCCC */
1640    mov     r0, rINST, lsr #8           @ r0<- A+
1641    mov     r1, rINST, lsr #12          @ r1<- B
1642    and     r0, r0, #15
1643    GET_VREG(r3, r1)                    @ r3<- vB
1644    GET_VREG(r2, r0)                    @ r2<- vA
1645    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1646    cmp     r2, r3                      @ compare (vA, vB)
1647    blt  1f                      @ branch to 1 if comparison failed
1648    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1649    movs    r9, r9, asl #1              @ convert to bytes, check sign
1650    bmi     common_backwardBranch       @ yes, do periodic checks
16511:
1652#if defined(WITH_JIT)
1653    GET_JIT_PROF_TABLE(r0)
1654    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1655    b        common_testUpdateProfile
1656#else
1657    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1658    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1659    GOTO_OPCODE(ip)                     @ jump to next instruction
1660#endif
1661
1662
1663/* ------------------------------ */
1664    .balign 64
1665.L_OP_IF_GT: /* 0x36 */
1666/* File: armv5te/OP_IF_GT.S */
1667/* File: armv5te/bincmp.S */
1668    /*
1669     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1670     * fragment that specifies the *reverse* comparison to perform, e.g.
1671     * for "if-le" you would use "gt".
1672     *
1673     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1674     */
1675    /* if-cmp vA, vB, +CCCC */
1676    mov     r0, rINST, lsr #8           @ r0<- A+
1677    mov     r1, rINST, lsr #12          @ r1<- B
1678    and     r0, r0, #15
1679    GET_VREG(r3, r1)                    @ r3<- vB
1680    GET_VREG(r2, r0)                    @ r2<- vA
1681    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1682    cmp     r2, r3                      @ compare (vA, vB)
1683    ble  1f                      @ branch to 1 if comparison failed
1684    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1685    movs    r9, r9, asl #1              @ convert to bytes, check sign
1686    bmi     common_backwardBranch       @ yes, do periodic checks
16871:
1688#if defined(WITH_JIT)
1689    GET_JIT_PROF_TABLE(r0)
1690    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1691    b        common_testUpdateProfile
1692#else
1693    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1694    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1695    GOTO_OPCODE(ip)                     @ jump to next instruction
1696#endif
1697
1698
1699/* ------------------------------ */
1700    .balign 64
1701.L_OP_IF_LE: /* 0x37 */
1702/* File: armv5te/OP_IF_LE.S */
1703/* File: armv5te/bincmp.S */
1704    /*
1705     * Generic two-operand compare-and-branch operation.  Provide a "revcmp"
1706     * fragment that specifies the *reverse* comparison to perform, e.g.
1707     * for "if-le" you would use "gt".
1708     *
1709     * For: if-eq, if-ne, if-lt, if-ge, if-gt, if-le
1710     */
1711    /* if-cmp vA, vB, +CCCC */
1712    mov     r0, rINST, lsr #8           @ r0<- A+
1713    mov     r1, rINST, lsr #12          @ r1<- B
1714    and     r0, r0, #15
1715    GET_VREG(r3, r1)                    @ r3<- vB
1716    GET_VREG(r2, r0)                    @ r2<- vA
1717    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1718    cmp     r2, r3                      @ compare (vA, vB)
1719    bgt  1f                      @ branch to 1 if comparison failed
1720    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1721    movs    r9, r9, asl #1              @ convert to bytes, check sign
1722    bmi     common_backwardBranch       @ yes, do periodic checks
17231:
1724#if defined(WITH_JIT)
1725    GET_JIT_PROF_TABLE(r0)
1726    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1727    b        common_testUpdateProfile
1728#else
1729    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1730    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1731    GOTO_OPCODE(ip)                     @ jump to next instruction
1732#endif
1733
1734
1735/* ------------------------------ */
1736    .balign 64
1737.L_OP_IF_EQZ: /* 0x38 */
1738/* File: armv5te/OP_IF_EQZ.S */
1739/* File: armv5te/zcmp.S */
1740    /*
1741     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1742     * fragment that specifies the *reverse* comparison to perform, e.g.
1743     * for "if-le" you would use "gt".
1744     *
1745     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1746     */
1747    /* if-cmp vAA, +BBBB */
1748    mov     r0, rINST, lsr #8           @ r0<- AA
1749    GET_VREG(r2, r0)                    @ r2<- vAA
1750    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1751    cmp     r2, #0                      @ compare (vA, 0)
1752    bne  1f                      @ branch to 1 if comparison failed
1753    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1754    movs    r9, r9, asl #1              @ convert to bytes, check sign
1755    bmi     common_backwardBranch       @ backward branch, do periodic checks
17561:
1757#if defined(WITH_JIT)
1758    GET_JIT_PROF_TABLE(r0)
1759    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1760    cmp     r0,#0
1761    bne     common_updateProfile
1762    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1763    GOTO_OPCODE(ip)                     @ jump to next instruction
1764#else
1765    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1766    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1767    GOTO_OPCODE(ip)                     @ jump to next instruction
1768#endif
1769
1770
1771/* ------------------------------ */
1772    .balign 64
1773.L_OP_IF_NEZ: /* 0x39 */
1774/* File: armv5te/OP_IF_NEZ.S */
1775/* File: armv5te/zcmp.S */
1776    /*
1777     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1778     * fragment that specifies the *reverse* comparison to perform, e.g.
1779     * for "if-le" you would use "gt".
1780     *
1781     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1782     */
1783    /* if-cmp vAA, +BBBB */
1784    mov     r0, rINST, lsr #8           @ r0<- AA
1785    GET_VREG(r2, r0)                    @ r2<- vAA
1786    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1787    cmp     r2, #0                      @ compare (vA, 0)
1788    beq  1f                      @ branch to 1 if comparison failed
1789    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1790    movs    r9, r9, asl #1              @ convert to bytes, check sign
1791    bmi     common_backwardBranch       @ backward branch, do periodic checks
17921:
1793#if defined(WITH_JIT)
1794    GET_JIT_PROF_TABLE(r0)
1795    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1796    cmp     r0,#0
1797    bne     common_updateProfile
1798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1799    GOTO_OPCODE(ip)                     @ jump to next instruction
1800#else
1801    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1802    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1803    GOTO_OPCODE(ip)                     @ jump to next instruction
1804#endif
1805
1806
1807/* ------------------------------ */
1808    .balign 64
1809.L_OP_IF_LTZ: /* 0x3a */
1810/* File: armv5te/OP_IF_LTZ.S */
1811/* File: armv5te/zcmp.S */
1812    /*
1813     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1814     * fragment that specifies the *reverse* comparison to perform, e.g.
1815     * for "if-le" you would use "gt".
1816     *
1817     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1818     */
1819    /* if-cmp vAA, +BBBB */
1820    mov     r0, rINST, lsr #8           @ r0<- AA
1821    GET_VREG(r2, r0)                    @ r2<- vAA
1822    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1823    cmp     r2, #0                      @ compare (vA, 0)
1824    bge  1f                      @ branch to 1 if comparison failed
1825    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1826    movs    r9, r9, asl #1              @ convert to bytes, check sign
1827    bmi     common_backwardBranch       @ backward branch, do periodic checks
18281:
1829#if defined(WITH_JIT)
1830    GET_JIT_PROF_TABLE(r0)
1831    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1832    cmp     r0,#0
1833    bne     common_updateProfile
1834    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1835    GOTO_OPCODE(ip)                     @ jump to next instruction
1836#else
1837    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1838    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1839    GOTO_OPCODE(ip)                     @ jump to next instruction
1840#endif
1841
1842
1843/* ------------------------------ */
1844    .balign 64
1845.L_OP_IF_GEZ: /* 0x3b */
1846/* File: armv5te/OP_IF_GEZ.S */
1847/* File: armv5te/zcmp.S */
1848    /*
1849     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1850     * fragment that specifies the *reverse* comparison to perform, e.g.
1851     * for "if-le" you would use "gt".
1852     *
1853     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1854     */
1855    /* if-cmp vAA, +BBBB */
1856    mov     r0, rINST, lsr #8           @ r0<- AA
1857    GET_VREG(r2, r0)                    @ r2<- vAA
1858    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1859    cmp     r2, #0                      @ compare (vA, 0)
1860    blt  1f                      @ branch to 1 if comparison failed
1861    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1862    movs    r9, r9, asl #1              @ convert to bytes, check sign
1863    bmi     common_backwardBranch       @ backward branch, do periodic checks
18641:
1865#if defined(WITH_JIT)
1866    GET_JIT_PROF_TABLE(r0)
1867    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1868    cmp     r0,#0
1869    bne     common_updateProfile
1870    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1871    GOTO_OPCODE(ip)                     @ jump to next instruction
1872#else
1873    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1874    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1875    GOTO_OPCODE(ip)                     @ jump to next instruction
1876#endif
1877
1878
1879/* ------------------------------ */
1880    .balign 64
1881.L_OP_IF_GTZ: /* 0x3c */
1882/* File: armv5te/OP_IF_GTZ.S */
1883/* File: armv5te/zcmp.S */
1884    /*
1885     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1886     * fragment that specifies the *reverse* comparison to perform, e.g.
1887     * for "if-le" you would use "gt".
1888     *
1889     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1890     */
1891    /* if-cmp vAA, +BBBB */
1892    mov     r0, rINST, lsr #8           @ r0<- AA
1893    GET_VREG(r2, r0)                    @ r2<- vAA
1894    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1895    cmp     r2, #0                      @ compare (vA, 0)
1896    ble  1f                      @ branch to 1 if comparison failed
1897    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1898    movs    r9, r9, asl #1              @ convert to bytes, check sign
1899    bmi     common_backwardBranch       @ backward branch, do periodic checks
19001:
1901#if defined(WITH_JIT)
1902    GET_JIT_PROF_TABLE(r0)
1903    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1904    cmp     r0,#0
1905    bne     common_updateProfile
1906    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1907    GOTO_OPCODE(ip)                     @ jump to next instruction
1908#else
1909    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1910    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1911    GOTO_OPCODE(ip)                     @ jump to next instruction
1912#endif
1913
1914
1915/* ------------------------------ */
1916    .balign 64
1917.L_OP_IF_LEZ: /* 0x3d */
1918/* File: armv5te/OP_IF_LEZ.S */
1919/* File: armv5te/zcmp.S */
1920    /*
1921     * Generic one-operand compare-and-branch operation.  Provide a "revcmp"
1922     * fragment that specifies the *reverse* comparison to perform, e.g.
1923     * for "if-le" you would use "gt".
1924     *
1925     * for: if-eqz, if-nez, if-ltz, if-gez, if-gtz, if-lez
1926     */
1927    /* if-cmp vAA, +BBBB */
1928    mov     r0, rINST, lsr #8           @ r0<- AA
1929    GET_VREG(r2, r0)                    @ r2<- vAA
1930    mov     r9, #4                      @ r0<- BYTE branch dist for not-taken
1931    cmp     r2, #0                      @ compare (vA, 0)
1932    bgt  1f                      @ branch to 1 if comparison failed
1933    FETCH_S(r9, 1)                      @ r9<- branch offset, in code units
1934    movs    r9, r9, asl #1              @ convert to bytes, check sign
1935    bmi     common_backwardBranch       @ backward branch, do periodic checks
19361:
1937#if defined(WITH_JIT)
1938    GET_JIT_PROF_TABLE(r0)
1939    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1940    cmp     r0,#0
1941    bne     common_updateProfile
1942    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1943    GOTO_OPCODE(ip)                     @ jump to next instruction
1944#else
1945    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
1946    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
1947    GOTO_OPCODE(ip)                     @ jump to next instruction
1948#endif
1949
1950
1951/* ------------------------------ */
1952    .balign 64
1953.L_OP_UNUSED_3E: /* 0x3e */
1954/* File: armv5te/OP_UNUSED_3E.S */
1955/* File: armv5te/unused.S */
1956    bl      common_abort
1957
1958
1959/* ------------------------------ */
1960    .balign 64
1961.L_OP_UNUSED_3F: /* 0x3f */
1962/* File: armv5te/OP_UNUSED_3F.S */
1963/* File: armv5te/unused.S */
1964    bl      common_abort
1965
1966
1967/* ------------------------------ */
1968    .balign 64
1969.L_OP_UNUSED_40: /* 0x40 */
1970/* File: armv5te/OP_UNUSED_40.S */
1971/* File: armv5te/unused.S */
1972    bl      common_abort
1973
1974
1975/* ------------------------------ */
1976    .balign 64
1977.L_OP_UNUSED_41: /* 0x41 */
1978/* File: armv5te/OP_UNUSED_41.S */
1979/* File: armv5te/unused.S */
1980    bl      common_abort
1981
1982
1983/* ------------------------------ */
1984    .balign 64
1985.L_OP_UNUSED_42: /* 0x42 */
1986/* File: armv5te/OP_UNUSED_42.S */
1987/* File: armv5te/unused.S */
1988    bl      common_abort
1989
1990
1991/* ------------------------------ */
1992    .balign 64
1993.L_OP_UNUSED_43: /* 0x43 */
1994/* File: armv5te/OP_UNUSED_43.S */
1995/* File: armv5te/unused.S */
1996    bl      common_abort
1997
1998
1999/* ------------------------------ */
2000    .balign 64
2001.L_OP_AGET: /* 0x44 */
2002/* File: armv5te/OP_AGET.S */
2003    /*
2004     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2005     *
2006     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2007     * instructions.  We use a pair of FETCH_Bs instead.
2008     *
2009     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2010     */
2011    /* op vAA, vBB, vCC */
2012    FETCH_B(r2, 1, 0)                   @ r2<- BB
2013    mov     r9, rINST, lsr #8           @ r9<- AA
2014    FETCH_B(r3, 1, 1)                   @ r3<- CC
2015    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2016    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2017    cmp     r0, #0                      @ null array object?
2018    beq     common_errNullObject        @ yes, bail
2019    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2020    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2021    cmp     r1, r3                      @ compare unsigned index, length
2022    bcs     common_errArrayIndex        @ index >= length, bail
2023    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2024    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2025    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2026    SET_VREG(r2, r9)                    @ vAA<- r2
2027    GOTO_OPCODE(ip)                     @ jump to next instruction
2028
2029/* ------------------------------ */
2030    .balign 64
2031.L_OP_AGET_WIDE: /* 0x45 */
2032/* File: armv4t/OP_AGET_WIDE.S */
2033    /*
2034     * Array get, 64 bits.  vAA <- vBB[vCC].
2035     *
2036     * Arrays of long/double are 64-bit aligned, so it's okay to use LDRD.
2037     */
2038    /* aget-wide vAA, vBB, vCC */
2039    FETCH(r0, 1)                        @ r0<- CCBB
2040    mov     r9, rINST, lsr #8           @ r9<- AA
2041    and     r2, r0, #255                @ r2<- BB
2042    mov     r3, r0, lsr #8              @ r3<- CC
2043    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2044    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2045    cmp     r0, #0                      @ null array object?
2046    beq     common_errNullObject        @ yes, bail
2047    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2048    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2049    cmp     r1, r3                      @ compare unsigned index, length
2050    bcc     .LOP_AGET_WIDE_finish          @ okay, continue below
2051    b       common_errArrayIndex        @ index >= length, bail
2052    @ May want to swap the order of these two branches depending on how the
2053    @ branch prediction (if any) handles conditional forward branches vs.
2054    @ unconditional forward branches.
2055
2056/* ------------------------------ */
2057    .balign 64
2058.L_OP_AGET_OBJECT: /* 0x46 */
2059/* File: armv5te/OP_AGET_OBJECT.S */
2060/* File: armv5te/OP_AGET.S */
2061    /*
2062     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2063     *
2064     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2065     * instructions.  We use a pair of FETCH_Bs instead.
2066     *
2067     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2068     */
2069    /* op vAA, vBB, vCC */
2070    FETCH_B(r2, 1, 0)                   @ r2<- BB
2071    mov     r9, rINST, lsr #8           @ r9<- AA
2072    FETCH_B(r3, 1, 1)                   @ r3<- CC
2073    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2074    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2075    cmp     r0, #0                      @ null array object?
2076    beq     common_errNullObject        @ yes, bail
2077    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2078    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2079    cmp     r1, r3                      @ compare unsigned index, length
2080    bcs     common_errArrayIndex        @ index >= length, bail
2081    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2082    ldr   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2083    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2084    SET_VREG(r2, r9)                    @ vAA<- r2
2085    GOTO_OPCODE(ip)                     @ jump to next instruction
2086
2087
2088/* ------------------------------ */
2089    .balign 64
2090.L_OP_AGET_BOOLEAN: /* 0x47 */
2091/* File: armv5te/OP_AGET_BOOLEAN.S */
2092/* File: armv5te/OP_AGET.S */
2093    /*
2094     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2095     *
2096     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2097     * instructions.  We use a pair of FETCH_Bs instead.
2098     *
2099     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2100     */
2101    /* op vAA, vBB, vCC */
2102    FETCH_B(r2, 1, 0)                   @ r2<- BB
2103    mov     r9, rINST, lsr #8           @ r9<- AA
2104    FETCH_B(r3, 1, 1)                   @ r3<- CC
2105    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2106    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2107    cmp     r0, #0                      @ null array object?
2108    beq     common_errNullObject        @ yes, bail
2109    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2110    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2111    cmp     r1, r3                      @ compare unsigned index, length
2112    bcs     common_errArrayIndex        @ index >= length, bail
2113    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2114    ldrb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2115    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2116    SET_VREG(r2, r9)                    @ vAA<- r2
2117    GOTO_OPCODE(ip)                     @ jump to next instruction
2118
2119
2120/* ------------------------------ */
2121    .balign 64
2122.L_OP_AGET_BYTE: /* 0x48 */
2123/* File: armv5te/OP_AGET_BYTE.S */
2124/* File: armv5te/OP_AGET.S */
2125    /*
2126     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2127     *
2128     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2129     * instructions.  We use a pair of FETCH_Bs instead.
2130     *
2131     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2132     */
2133    /* op vAA, vBB, vCC */
2134    FETCH_B(r2, 1, 0)                   @ r2<- BB
2135    mov     r9, rINST, lsr #8           @ r9<- AA
2136    FETCH_B(r3, 1, 1)                   @ r3<- CC
2137    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2138    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2139    cmp     r0, #0                      @ null array object?
2140    beq     common_errNullObject        @ yes, bail
2141    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2142    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2143    cmp     r1, r3                      @ compare unsigned index, length
2144    bcs     common_errArrayIndex        @ index >= length, bail
2145    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2146    ldrsb   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2147    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2148    SET_VREG(r2, r9)                    @ vAA<- r2
2149    GOTO_OPCODE(ip)                     @ jump to next instruction
2150
2151
2152/* ------------------------------ */
2153    .balign 64
2154.L_OP_AGET_CHAR: /* 0x49 */
2155/* File: armv5te/OP_AGET_CHAR.S */
2156/* File: armv5te/OP_AGET.S */
2157    /*
2158     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2159     *
2160     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2161     * instructions.  We use a pair of FETCH_Bs instead.
2162     *
2163     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2164     */
2165    /* op vAA, vBB, vCC */
2166    FETCH_B(r2, 1, 0)                   @ r2<- BB
2167    mov     r9, rINST, lsr #8           @ r9<- AA
2168    FETCH_B(r3, 1, 1)                   @ r3<- CC
2169    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2170    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2171    cmp     r0, #0                      @ null array object?
2172    beq     common_errNullObject        @ yes, bail
2173    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2174    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2175    cmp     r1, r3                      @ compare unsigned index, length
2176    bcs     common_errArrayIndex        @ index >= length, bail
2177    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2178    ldrh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2179    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2180    SET_VREG(r2, r9)                    @ vAA<- r2
2181    GOTO_OPCODE(ip)                     @ jump to next instruction
2182
2183
2184/* ------------------------------ */
2185    .balign 64
2186.L_OP_AGET_SHORT: /* 0x4a */
2187/* File: armv5te/OP_AGET_SHORT.S */
2188/* File: armv5te/OP_AGET.S */
2189    /*
2190     * Array get, 32 bits or less.  vAA <- vBB[vCC].
2191     *
2192     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2193     * instructions.  We use a pair of FETCH_Bs instead.
2194     *
2195     * for: aget, aget-object, aget-boolean, aget-byte, aget-char, aget-short
2196     */
2197    /* op vAA, vBB, vCC */
2198    FETCH_B(r2, 1, 0)                   @ r2<- BB
2199    mov     r9, rINST, lsr #8           @ r9<- AA
2200    FETCH_B(r3, 1, 1)                   @ r3<- CC
2201    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2202    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2203    cmp     r0, #0                      @ null array object?
2204    beq     common_errNullObject        @ yes, bail
2205    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2206    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2207    cmp     r1, r3                      @ compare unsigned index, length
2208    bcs     common_errArrayIndex        @ index >= length, bail
2209    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2210    ldrsh   r2, [r0, #offArrayObject_contents]  @ r2<- vBB[vCC]
2211    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2212    SET_VREG(r2, r9)                    @ vAA<- r2
2213    GOTO_OPCODE(ip)                     @ jump to next instruction
2214
2215
2216/* ------------------------------ */
2217    .balign 64
2218.L_OP_APUT: /* 0x4b */
2219/* File: armv5te/OP_APUT.S */
2220    /*
2221     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2222     *
2223     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2224     * instructions.  We use a pair of FETCH_Bs instead.
2225     *
2226     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2227     */
2228    /* op vAA, vBB, vCC */
2229    FETCH_B(r2, 1, 0)                   @ r2<- BB
2230    mov     r9, rINST, lsr #8           @ r9<- AA
2231    FETCH_B(r3, 1, 1)                   @ r3<- CC
2232    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2233    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2234    cmp     r0, #0                      @ null array object?
2235    beq     common_errNullObject        @ yes, bail
2236    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2237    add     r0, r0, r1, lsl #2     @ r0<- arrayObj + index*width
2238    cmp     r1, r3                      @ compare unsigned index, length
2239    bcs     common_errArrayIndex        @ index >= length, bail
2240    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2241    GET_VREG(r2, r9)                    @ r2<- vAA
2242    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2243    str  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2244    GOTO_OPCODE(ip)                     @ jump to next instruction
2245
2246/* ------------------------------ */
2247    .balign 64
2248.L_OP_APUT_WIDE: /* 0x4c */
2249/* File: armv4t/OP_APUT_WIDE.S */
2250    /*
2251     * Array put, 64 bits.  vBB[vCC] <- vAA.
2252     */
2253    /* aput-wide vAA, vBB, vCC */
2254    FETCH(r0, 1)                        @ r0<- CCBB
2255    mov     r9, rINST, lsr #8           @ r9<- AA
2256    and     r2, r0, #255                @ r2<- BB
2257    mov     r3, r0, lsr #8              @ r3<- CC
2258    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2259    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2260    cmp     r0, #0                      @ null array object?
2261    beq     common_errNullObject        @ yes, bail
2262    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2263    add     r0, r0, r1, lsl #3          @ r0<- arrayObj + index*width
2264    cmp     r1, r3                      @ compare unsigned index, length
2265    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2266    bcc     .LOP_APUT_WIDE_finish          @ okay, continue below
2267    b       common_errArrayIndex        @ index >= length, bail
2268    @ May want to swap the order of these two branches depending on how the
2269    @ branch prediction (if any) handles conditional forward branches vs.
2270    @ unconditional forward branches.
2271
2272/* ------------------------------ */
2273    .balign 64
2274.L_OP_APUT_OBJECT: /* 0x4d */
2275/* File: armv5te/OP_APUT_OBJECT.S */
2276    /*
2277     * Store an object into an array.  vBB[vCC] <- vAA.
2278     *
2279     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2280     * instructions.  We use a pair of FETCH_Bs instead.
2281     */
2282    /* op vAA, vBB, vCC */
2283    FETCH(r0, 1)                        @ r0<- CCBB
2284    mov     r9, rINST, lsr #8           @ r9<- AA
2285    and     r2, r0, #255                @ r2<- BB
2286    mov     r3, r0, lsr #8              @ r3<- CC
2287    GET_VREG(rINST, r2)                 @ rINST<- vBB (array object)
2288    GET_VREG(r0, r3)                    @ r0<- vCC (requested index)
2289    cmp     rINST, #0                   @ null array object?
2290    GET_VREG(r9, r9)                    @ r9<- vAA
2291    beq     common_errNullObject        @ yes, bail
2292    ldr     r3, [rINST, #offArrayObject_length]   @ r3<- arrayObj->length
2293    add     r10, rINST, r0, lsl #2      @ r10<- arrayObj + index*width
2294    cmp     r0, r3                      @ compare unsigned index, length
2295    bcc     .LOP_APUT_OBJECT_finish          @ we're okay, continue on
2296    b       common_errArrayIndex        @ index >= length, bail
2297
2298
2299/* ------------------------------ */
2300    .balign 64
2301.L_OP_APUT_BOOLEAN: /* 0x4e */
2302/* File: armv5te/OP_APUT_BOOLEAN.S */
2303/* File: armv5te/OP_APUT.S */
2304    /*
2305     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2306     *
2307     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2308     * instructions.  We use a pair of FETCH_Bs instead.
2309     *
2310     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2311     */
2312    /* op vAA, vBB, vCC */
2313    FETCH_B(r2, 1, 0)                   @ r2<- BB
2314    mov     r9, rINST, lsr #8           @ r9<- AA
2315    FETCH_B(r3, 1, 1)                   @ r3<- CC
2316    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2317    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2318    cmp     r0, #0                      @ null array object?
2319    beq     common_errNullObject        @ yes, bail
2320    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2321    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2322    cmp     r1, r3                      @ compare unsigned index, length
2323    bcs     common_errArrayIndex        @ index >= length, bail
2324    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2325    GET_VREG(r2, r9)                    @ r2<- vAA
2326    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2327    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2328    GOTO_OPCODE(ip)                     @ jump to next instruction
2329
2330
2331/* ------------------------------ */
2332    .balign 64
2333.L_OP_APUT_BYTE: /* 0x4f */
2334/* File: armv5te/OP_APUT_BYTE.S */
2335/* File: armv5te/OP_APUT.S */
2336    /*
2337     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2338     *
2339     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2340     * instructions.  We use a pair of FETCH_Bs instead.
2341     *
2342     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2343     */
2344    /* op vAA, vBB, vCC */
2345    FETCH_B(r2, 1, 0)                   @ r2<- BB
2346    mov     r9, rINST, lsr #8           @ r9<- AA
2347    FETCH_B(r3, 1, 1)                   @ r3<- CC
2348    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2349    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2350    cmp     r0, #0                      @ null array object?
2351    beq     common_errNullObject        @ yes, bail
2352    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2353    add     r0, r0, r1, lsl #0     @ r0<- arrayObj + index*width
2354    cmp     r1, r3                      @ compare unsigned index, length
2355    bcs     common_errArrayIndex        @ index >= length, bail
2356    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2357    GET_VREG(r2, r9)                    @ r2<- vAA
2358    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2359    strb  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2360    GOTO_OPCODE(ip)                     @ jump to next instruction
2361
2362
2363/* ------------------------------ */
2364    .balign 64
2365.L_OP_APUT_CHAR: /* 0x50 */
2366/* File: armv5te/OP_APUT_CHAR.S */
2367/* File: armv5te/OP_APUT.S */
2368    /*
2369     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2370     *
2371     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2372     * instructions.  We use a pair of FETCH_Bs instead.
2373     *
2374     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2375     */
2376    /* op vAA, vBB, vCC */
2377    FETCH_B(r2, 1, 0)                   @ r2<- BB
2378    mov     r9, rINST, lsr #8           @ r9<- AA
2379    FETCH_B(r3, 1, 1)                   @ r3<- CC
2380    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2381    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2382    cmp     r0, #0                      @ null array object?
2383    beq     common_errNullObject        @ yes, bail
2384    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2385    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2386    cmp     r1, r3                      @ compare unsigned index, length
2387    bcs     common_errArrayIndex        @ index >= length, bail
2388    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2389    GET_VREG(r2, r9)                    @ r2<- vAA
2390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2391    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2392    GOTO_OPCODE(ip)                     @ jump to next instruction
2393
2394
2395/* ------------------------------ */
2396    .balign 64
2397.L_OP_APUT_SHORT: /* 0x51 */
2398/* File: armv5te/OP_APUT_SHORT.S */
2399/* File: armv5te/OP_APUT.S */
2400    /*
2401     * Array put, 32 bits or less.  vBB[vCC] <- vAA.
2402     *
2403     * Note: using the usual FETCH/and/shift stuff, this fits in exactly 17
2404     * instructions.  We use a pair of FETCH_Bs instead.
2405     *
2406     * for: aput, aput-boolean, aput-byte, aput-char, aput-short
2407     */
2408    /* op vAA, vBB, vCC */
2409    FETCH_B(r2, 1, 0)                   @ r2<- BB
2410    mov     r9, rINST, lsr #8           @ r9<- AA
2411    FETCH_B(r3, 1, 1)                   @ r3<- CC
2412    GET_VREG(r0, r2)                    @ r0<- vBB (array object)
2413    GET_VREG(r1, r3)                    @ r1<- vCC (requested index)
2414    cmp     r0, #0                      @ null array object?
2415    beq     common_errNullObject        @ yes, bail
2416    ldr     r3, [r0, #offArrayObject_length]    @ r3<- arrayObj->length
2417    add     r0, r0, r1, lsl #1     @ r0<- arrayObj + index*width
2418    cmp     r1, r3                      @ compare unsigned index, length
2419    bcs     common_errArrayIndex        @ index >= length, bail
2420    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2421    GET_VREG(r2, r9)                    @ r2<- vAA
2422    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2423    strh  r2, [r0, #offArrayObject_contents]  @ vBB[vCC]<- r2
2424    GOTO_OPCODE(ip)                     @ jump to next instruction
2425
2426
2427/* ------------------------------ */
2428    .balign 64
2429.L_OP_IGET: /* 0x52 */
2430/* File: armv5te/OP_IGET.S */
2431    /*
2432     * General 32-bit instance field get.
2433     *
2434     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2435     */
2436    /* op vA, vB, field@CCCC */
2437    mov     r0, rINST, lsr #12          @ r0<- B
2438    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2439    FETCH(r1, 1)                        @ r1<- field ref CCCC
2440    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2441    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2442    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2443    cmp     r0, #0                      @ is resolved entry null?
2444    bne     .LOP_IGET_finish          @ no, already resolved
24458:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2446    EXPORT_PC()                         @ resolve() could throw
2447    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2448    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2449    cmp     r0, #0
2450    bne     .LOP_IGET_finish
2451    b       common_exceptionThrown
2452
2453/* ------------------------------ */
2454    .balign 64
2455.L_OP_IGET_WIDE: /* 0x53 */
2456/* File: armv4t/OP_IGET_WIDE.S */
2457    /*
2458     * Wide 32-bit instance field get.
2459     */
2460    /* iget-wide vA, vB, field@CCCC */
2461    mov     r0, rINST, lsr #12          @ r0<- B
2462    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2463    FETCH(r1, 1)                        @ r1<- field ref CCCC
2464    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2465    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2466    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2467    cmp     r0, #0                      @ is resolved entry null?
2468    bne     .LOP_IGET_WIDE_finish          @ no, already resolved
24698:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2470    EXPORT_PC()                         @ resolve() could throw
2471    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2472    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2473    cmp     r0, #0
2474    bne     .LOP_IGET_WIDE_finish
2475    b       common_exceptionThrown
2476
2477/* ------------------------------ */
2478    .balign 64
2479.L_OP_IGET_OBJECT: /* 0x54 */
2480/* File: armv5te/OP_IGET_OBJECT.S */
2481/* File: armv5te/OP_IGET.S */
2482    /*
2483     * General 32-bit instance field get.
2484     *
2485     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2486     */
2487    /* op vA, vB, field@CCCC */
2488    mov     r0, rINST, lsr #12          @ r0<- B
2489    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2490    FETCH(r1, 1)                        @ r1<- field ref CCCC
2491    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2492    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2493    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2494    cmp     r0, #0                      @ is resolved entry null?
2495    bne     .LOP_IGET_OBJECT_finish          @ no, already resolved
24968:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2497    EXPORT_PC()                         @ resolve() could throw
2498    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2499    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2500    cmp     r0, #0
2501    bne     .LOP_IGET_OBJECT_finish
2502    b       common_exceptionThrown
2503
2504
2505/* ------------------------------ */
2506    .balign 64
2507.L_OP_IGET_BOOLEAN: /* 0x55 */
2508/* File: armv5te/OP_IGET_BOOLEAN.S */
2509@include "armv5te/OP_IGET.S" { "load":"ldrb", "sqnum":"1" }
2510/* File: armv5te/OP_IGET.S */
2511    /*
2512     * General 32-bit instance field get.
2513     *
2514     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2515     */
2516    /* op vA, vB, field@CCCC */
2517    mov     r0, rINST, lsr #12          @ r0<- B
2518    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2519    FETCH(r1, 1)                        @ r1<- field ref CCCC
2520    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2521    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2522    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2523    cmp     r0, #0                      @ is resolved entry null?
2524    bne     .LOP_IGET_BOOLEAN_finish          @ no, already resolved
25258:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2526    EXPORT_PC()                         @ resolve() could throw
2527    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2528    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2529    cmp     r0, #0
2530    bne     .LOP_IGET_BOOLEAN_finish
2531    b       common_exceptionThrown
2532
2533
2534/* ------------------------------ */
2535    .balign 64
2536.L_OP_IGET_BYTE: /* 0x56 */
2537/* File: armv5te/OP_IGET_BYTE.S */
2538@include "armv5te/OP_IGET.S" { "load":"ldrsb", "sqnum":"2" }
2539/* File: armv5te/OP_IGET.S */
2540    /*
2541     * General 32-bit instance field get.
2542     *
2543     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2544     */
2545    /* op vA, vB, field@CCCC */
2546    mov     r0, rINST, lsr #12          @ r0<- B
2547    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2548    FETCH(r1, 1)                        @ r1<- field ref CCCC
2549    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2550    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2551    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2552    cmp     r0, #0                      @ is resolved entry null?
2553    bne     .LOP_IGET_BYTE_finish          @ no, already resolved
25548:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2555    EXPORT_PC()                         @ resolve() could throw
2556    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2557    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2558    cmp     r0, #0
2559    bne     .LOP_IGET_BYTE_finish
2560    b       common_exceptionThrown
2561
2562
2563/* ------------------------------ */
2564    .balign 64
2565.L_OP_IGET_CHAR: /* 0x57 */
2566/* File: armv5te/OP_IGET_CHAR.S */
2567@include "armv5te/OP_IGET.S" { "load":"ldrh", "sqnum":"3" }
2568/* File: armv5te/OP_IGET.S */
2569    /*
2570     * General 32-bit instance field get.
2571     *
2572     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2573     */
2574    /* op vA, vB, field@CCCC */
2575    mov     r0, rINST, lsr #12          @ r0<- B
2576    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2577    FETCH(r1, 1)                        @ r1<- field ref CCCC
2578    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2579    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2580    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2581    cmp     r0, #0                      @ is resolved entry null?
2582    bne     .LOP_IGET_CHAR_finish          @ no, already resolved
25838:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2584    EXPORT_PC()                         @ resolve() could throw
2585    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2586    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2587    cmp     r0, #0
2588    bne     .LOP_IGET_CHAR_finish
2589    b       common_exceptionThrown
2590
2591
2592/* ------------------------------ */
2593    .balign 64
2594.L_OP_IGET_SHORT: /* 0x58 */
2595/* File: armv5te/OP_IGET_SHORT.S */
2596@include "armv5te/OP_IGET.S" { "load":"ldrsh", "sqnum":"4" }
2597/* File: armv5te/OP_IGET.S */
2598    /*
2599     * General 32-bit instance field get.
2600     *
2601     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
2602     */
2603    /* op vA, vB, field@CCCC */
2604    mov     r0, rINST, lsr #12          @ r0<- B
2605    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2606    FETCH(r1, 1)                        @ r1<- field ref CCCC
2607    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2608    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2609    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2610    cmp     r0, #0                      @ is resolved entry null?
2611    bne     .LOP_IGET_SHORT_finish          @ no, already resolved
26128:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2613    EXPORT_PC()                         @ resolve() could throw
2614    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2615    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2616    cmp     r0, #0
2617    bne     .LOP_IGET_SHORT_finish
2618    b       common_exceptionThrown
2619
2620
2621/* ------------------------------ */
2622    .balign 64
2623.L_OP_IPUT: /* 0x59 */
2624/* File: armv5te/OP_IPUT.S */
2625    /*
2626     * General 32-bit instance field put.
2627     *
2628     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2629     */
2630    /* op vA, vB, field@CCCC */
2631    mov     r0, rINST, lsr #12          @ r0<- B
2632    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2633    FETCH(r1, 1)                        @ r1<- field ref CCCC
2634    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2635    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2636    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2637    cmp     r0, #0                      @ is resolved entry null?
2638    bne     .LOP_IPUT_finish          @ no, already resolved
26398:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2640    EXPORT_PC()                         @ resolve() could throw
2641    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2642    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2643    cmp     r0, #0                      @ success?
2644    bne     .LOP_IPUT_finish          @ yes, finish up
2645    b       common_exceptionThrown
2646
2647/* ------------------------------ */
2648    .balign 64
2649.L_OP_IPUT_WIDE: /* 0x5a */
2650/* File: armv4t/OP_IPUT_WIDE.S */
2651    /* iput-wide vA, vB, field@CCCC */
2652    mov     r0, rINST, lsr #12          @ r0<- B
2653    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2654    FETCH(r1, 1)                        @ r1<- field ref CCCC
2655    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
2656    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2657    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2658    cmp     r0, #0                      @ is resolved entry null?
2659    bne     .LOP_IPUT_WIDE_finish          @ no, already resolved
26608:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
2661    EXPORT_PC()                         @ resolve() could throw
2662    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2663    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2664    cmp     r0, #0                      @ success?
2665    bne     .LOP_IPUT_WIDE_finish          @ yes, finish up
2666    b       common_exceptionThrown
2667
2668/* ------------------------------ */
2669    .balign 64
2670.L_OP_IPUT_OBJECT: /* 0x5b */
2671/* File: armv5te/OP_IPUT_OBJECT.S */
2672    /*
2673     * 32-bit instance field put.
2674     *
2675     * for: iput-object, iput-object-volatile
2676     */
2677    /* op vA, vB, field@CCCC */
2678    mov     r0, rINST, lsr #12          @ r0<- B
2679    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2680    FETCH(r1, 1)                        @ r1<- field ref CCCC
2681    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2682    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2683    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2684    cmp     r0, #0                      @ is resolved entry null?
2685    bne     .LOP_IPUT_OBJECT_finish          @ no, already resolved
26868:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2687    EXPORT_PC()                         @ resolve() could throw
2688    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2689    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2690    cmp     r0, #0                      @ success?
2691    bne     .LOP_IPUT_OBJECT_finish          @ yes, finish up
2692    b       common_exceptionThrown
2693
2694/* ------------------------------ */
2695    .balign 64
2696.L_OP_IPUT_BOOLEAN: /* 0x5c */
2697/* File: armv5te/OP_IPUT_BOOLEAN.S */
2698@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"1" }
2699/* File: armv5te/OP_IPUT.S */
2700    /*
2701     * General 32-bit instance field put.
2702     *
2703     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2704     */
2705    /* op vA, vB, field@CCCC */
2706    mov     r0, rINST, lsr #12          @ r0<- B
2707    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2708    FETCH(r1, 1)                        @ r1<- field ref CCCC
2709    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2710    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2711    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2712    cmp     r0, #0                      @ is resolved entry null?
2713    bne     .LOP_IPUT_BOOLEAN_finish          @ no, already resolved
27148:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2715    EXPORT_PC()                         @ resolve() could throw
2716    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2717    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2718    cmp     r0, #0                      @ success?
2719    bne     .LOP_IPUT_BOOLEAN_finish          @ yes, finish up
2720    b       common_exceptionThrown
2721
2722
2723/* ------------------------------ */
2724    .balign 64
2725.L_OP_IPUT_BYTE: /* 0x5d */
2726/* File: armv5te/OP_IPUT_BYTE.S */
2727@include "armv5te/OP_IPUT.S" { "store":"strb", "sqnum":"2" }
2728/* File: armv5te/OP_IPUT.S */
2729    /*
2730     * General 32-bit instance field put.
2731     *
2732     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2733     */
2734    /* op vA, vB, field@CCCC */
2735    mov     r0, rINST, lsr #12          @ r0<- B
2736    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2737    FETCH(r1, 1)                        @ r1<- field ref CCCC
2738    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2739    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2740    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2741    cmp     r0, #0                      @ is resolved entry null?
2742    bne     .LOP_IPUT_BYTE_finish          @ no, already resolved
27438:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2744    EXPORT_PC()                         @ resolve() could throw
2745    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2746    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2747    cmp     r0, #0                      @ success?
2748    bne     .LOP_IPUT_BYTE_finish          @ yes, finish up
2749    b       common_exceptionThrown
2750
2751
2752/* ------------------------------ */
2753    .balign 64
2754.L_OP_IPUT_CHAR: /* 0x5e */
2755/* File: armv5te/OP_IPUT_CHAR.S */
2756@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"3" }
2757/* File: armv5te/OP_IPUT.S */
2758    /*
2759     * General 32-bit instance field put.
2760     *
2761     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2762     */
2763    /* op vA, vB, field@CCCC */
2764    mov     r0, rINST, lsr #12          @ r0<- B
2765    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2766    FETCH(r1, 1)                        @ r1<- field ref CCCC
2767    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2768    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2769    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2770    cmp     r0, #0                      @ is resolved entry null?
2771    bne     .LOP_IPUT_CHAR_finish          @ no, already resolved
27728:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2773    EXPORT_PC()                         @ resolve() could throw
2774    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2775    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2776    cmp     r0, #0                      @ success?
2777    bne     .LOP_IPUT_CHAR_finish          @ yes, finish up
2778    b       common_exceptionThrown
2779
2780
2781/* ------------------------------ */
2782    .balign 64
2783.L_OP_IPUT_SHORT: /* 0x5f */
2784/* File: armv5te/OP_IPUT_SHORT.S */
2785@include "armv5te/OP_IPUT.S" { "store":"strh", "sqnum":"4" }
2786/* File: armv5te/OP_IPUT.S */
2787    /*
2788     * General 32-bit instance field put.
2789     *
2790     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
2791     */
2792    /* op vA, vB, field@CCCC */
2793    mov     r0, rINST, lsr #12          @ r0<- B
2794    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
2795    FETCH(r1, 1)                        @ r1<- field ref CCCC
2796    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
2797    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
2798    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
2799    cmp     r0, #0                      @ is resolved entry null?
2800    bne     .LOP_IPUT_SHORT_finish          @ no, already resolved
28018:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
2802    EXPORT_PC()                         @ resolve() could throw
2803    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
2804    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
2805    cmp     r0, #0                      @ success?
2806    bne     .LOP_IPUT_SHORT_finish          @ yes, finish up
2807    b       common_exceptionThrown
2808
2809
2810/* ------------------------------ */
2811    .balign 64
2812.L_OP_SGET: /* 0x60 */
2813/* File: armv5te/OP_SGET.S */
2814    /*
2815     * General 32-bit SGET handler.
2816     *
2817     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2818     */
2819    /* op vAA, field@BBBB */
2820    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2821    FETCH(r1, 1)                        @ r1<- field ref BBBB
2822    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2823    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2824    cmp     r0, #0                      @ is resolved entry null?
2825    beq     .LOP_SGET_resolve         @ yes, do resolve
2826.LOP_SGET_finish: @ field ptr in r0
2827    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2828    @ no-op                             @ acquiring load
2829    mov     r2, rINST, lsr #8           @ r2<- AA
2830    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2831    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2832    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2833    GOTO_OPCODE(ip)                     @ jump to next instruction
2834
2835/* ------------------------------ */
2836    .balign 64
2837.L_OP_SGET_WIDE: /* 0x61 */
2838/* File: armv4t/OP_SGET_WIDE.S */
2839    /*
2840     * 64-bit SGET handler.
2841     */
2842    /* sget-wide vAA, field@BBBB */
2843    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2844    FETCH(r1, 1)                        @ r1<- field ref BBBB
2845    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2846    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2847    cmp     r0, #0                      @ is resolved entry null?
2848    beq     .LOP_SGET_WIDE_resolve         @ yes, do resolve
2849.LOP_SGET_WIDE_finish:
2850    mov     r9, rINST, lsr #8           @ r9<- AA
2851    add     r0, r0, #offStaticField_value @ r0<- pointer to data
2852    .if 0
2853    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
2854    .else
2855    ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
2856    .endif
2857    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
2858    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2859    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
2860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2861    GOTO_OPCODE(ip)                     @ jump to next instruction
2862
2863/* ------------------------------ */
2864    .balign 64
2865.L_OP_SGET_OBJECT: /* 0x62 */
2866/* File: armv5te/OP_SGET_OBJECT.S */
2867/* File: armv5te/OP_SGET.S */
2868    /*
2869     * General 32-bit SGET handler.
2870     *
2871     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2872     */
2873    /* op vAA, field@BBBB */
2874    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2875    FETCH(r1, 1)                        @ r1<- field ref BBBB
2876    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2877    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2878    cmp     r0, #0                      @ is resolved entry null?
2879    beq     .LOP_SGET_OBJECT_resolve         @ yes, do resolve
2880.LOP_SGET_OBJECT_finish: @ field ptr in r0
2881    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2882    @ no-op                             @ acquiring load
2883    mov     r2, rINST, lsr #8           @ r2<- AA
2884    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2885    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2886    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2887    GOTO_OPCODE(ip)                     @ jump to next instruction
2888
2889
2890/* ------------------------------ */
2891    .balign 64
2892.L_OP_SGET_BOOLEAN: /* 0x63 */
2893/* File: armv5te/OP_SGET_BOOLEAN.S */
2894/* File: armv5te/OP_SGET.S */
2895    /*
2896     * General 32-bit SGET handler.
2897     *
2898     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2899     */
2900    /* op vAA, field@BBBB */
2901    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2902    FETCH(r1, 1)                        @ r1<- field ref BBBB
2903    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2904    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2905    cmp     r0, #0                      @ is resolved entry null?
2906    beq     .LOP_SGET_BOOLEAN_resolve         @ yes, do resolve
2907.LOP_SGET_BOOLEAN_finish: @ field ptr in r0
2908    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2909    @ no-op                             @ acquiring load
2910    mov     r2, rINST, lsr #8           @ r2<- AA
2911    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2912    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2913    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2914    GOTO_OPCODE(ip)                     @ jump to next instruction
2915
2916
2917/* ------------------------------ */
2918    .balign 64
2919.L_OP_SGET_BYTE: /* 0x64 */
2920/* File: armv5te/OP_SGET_BYTE.S */
2921/* File: armv5te/OP_SGET.S */
2922    /*
2923     * General 32-bit SGET handler.
2924     *
2925     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2926     */
2927    /* op vAA, field@BBBB */
2928    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2929    FETCH(r1, 1)                        @ r1<- field ref BBBB
2930    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2931    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2932    cmp     r0, #0                      @ is resolved entry null?
2933    beq     .LOP_SGET_BYTE_resolve         @ yes, do resolve
2934.LOP_SGET_BYTE_finish: @ field ptr in r0
2935    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2936    @ no-op                             @ acquiring load
2937    mov     r2, rINST, lsr #8           @ r2<- AA
2938    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2939    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2940    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2941    GOTO_OPCODE(ip)                     @ jump to next instruction
2942
2943
2944/* ------------------------------ */
2945    .balign 64
2946.L_OP_SGET_CHAR: /* 0x65 */
2947/* File: armv5te/OP_SGET_CHAR.S */
2948/* File: armv5te/OP_SGET.S */
2949    /*
2950     * General 32-bit SGET handler.
2951     *
2952     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2953     */
2954    /* op vAA, field@BBBB */
2955    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2956    FETCH(r1, 1)                        @ r1<- field ref BBBB
2957    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2958    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2959    cmp     r0, #0                      @ is resolved entry null?
2960    beq     .LOP_SGET_CHAR_resolve         @ yes, do resolve
2961.LOP_SGET_CHAR_finish: @ field ptr in r0
2962    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2963    @ no-op                             @ acquiring load
2964    mov     r2, rINST, lsr #8           @ r2<- AA
2965    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2966    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2967    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2968    GOTO_OPCODE(ip)                     @ jump to next instruction
2969
2970
2971/* ------------------------------ */
2972    .balign 64
2973.L_OP_SGET_SHORT: /* 0x66 */
2974/* File: armv5te/OP_SGET_SHORT.S */
2975/* File: armv5te/OP_SGET.S */
2976    /*
2977     * General 32-bit SGET handler.
2978     *
2979     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
2980     */
2981    /* op vAA, field@BBBB */
2982    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
2983    FETCH(r1, 1)                        @ r1<- field ref BBBB
2984    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
2985    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
2986    cmp     r0, #0                      @ is resolved entry null?
2987    beq     .LOP_SGET_SHORT_resolve         @ yes, do resolve
2988.LOP_SGET_SHORT_finish: @ field ptr in r0
2989    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
2990    @ no-op                             @ acquiring load
2991    mov     r2, rINST, lsr #8           @ r2<- AA
2992    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
2993    SET_VREG(r1, r2)                    @ fp[AA]<- r1
2994    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
2995    GOTO_OPCODE(ip)                     @ jump to next instruction
2996
2997
2998/* ------------------------------ */
2999    .balign 64
3000.L_OP_SPUT: /* 0x67 */
3001/* File: armv5te/OP_SPUT.S */
3002    /*
3003     * General 32-bit SPUT handler.
3004     *
3005     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3006     */
3007    /* op vAA, field@BBBB */
3008    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3009    FETCH(r1, 1)                        @ r1<- field ref BBBB
3010    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3011    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3012    cmp     r0, #0                      @ is resolved entry null?
3013    beq     .LOP_SPUT_resolve         @ yes, do resolve
3014.LOP_SPUT_finish:   @ field ptr in r0
3015    mov     r2, rINST, lsr #8           @ r2<- AA
3016    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3017    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3018    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3019    @ no-op                             @ releasing store
3020    str     r1, [r0, #offStaticField_value] @ field<- vAA
3021    GOTO_OPCODE(ip)                     @ jump to next instruction
3022
3023/* ------------------------------ */
3024    .balign 64
3025.L_OP_SPUT_WIDE: /* 0x68 */
3026/* File: armv4t/OP_SPUT_WIDE.S */
3027    /*
3028     * 64-bit SPUT handler.
3029     */
3030    /* sput-wide vAA, field@BBBB */
3031    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
3032    FETCH(r1, 1)                        @ r1<- field ref BBBB
3033    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
3034    mov     r9, rINST, lsr #8           @ r9<- AA
3035    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
3036    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
3037    cmp     r2, #0                      @ is resolved entry null?
3038    beq     .LOP_SPUT_WIDE_resolve         @ yes, do resolve
3039.LOP_SPUT_WIDE_finish: @ field ptr in r2, AA in r9
3040    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3041    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
3042    GET_INST_OPCODE(r10)                @ extract opcode from rINST
3043    add     r2, r2, #offStaticField_value @ r2<- pointer to data
3044    .if 0
3045    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
3046    .else
3047    stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
3048    .endif
3049    GOTO_OPCODE(r10)                    @ jump to next instruction
3050
3051/* ------------------------------ */
3052    .balign 64
3053.L_OP_SPUT_OBJECT: /* 0x69 */
3054/* File: armv5te/OP_SPUT_OBJECT.S */
3055    /*
3056     * 32-bit SPUT handler for objects
3057     *
3058     * for: sput-object, sput-object-volatile
3059     */
3060    /* op vAA, field@BBBB */
3061    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3062    FETCH(r1, 1)                        @ r1<- field ref BBBB
3063    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3064    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3065    cmp     r0, #0                      @ is resolved entry null?
3066    bne     .LOP_SPUT_OBJECT_finish          @ no, continue
3067    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
3068    EXPORT_PC()                         @ resolve() could throw, so export now
3069    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
3070    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
3071    cmp     r0, #0                      @ success?
3072    bne     .LOP_SPUT_OBJECT_finish          @ yes, finish
3073    b       common_exceptionThrown      @ no, handle exception
3074
3075
3076/* ------------------------------ */
3077    .balign 64
3078.L_OP_SPUT_BOOLEAN: /* 0x6a */
3079/* File: armv5te/OP_SPUT_BOOLEAN.S */
3080/* File: armv5te/OP_SPUT.S */
3081    /*
3082     * General 32-bit SPUT handler.
3083     *
3084     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3085     */
3086    /* op vAA, field@BBBB */
3087    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3088    FETCH(r1, 1)                        @ r1<- field ref BBBB
3089    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3090    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3091    cmp     r0, #0                      @ is resolved entry null?
3092    beq     .LOP_SPUT_BOOLEAN_resolve         @ yes, do resolve
3093.LOP_SPUT_BOOLEAN_finish:   @ field ptr in r0
3094    mov     r2, rINST, lsr #8           @ r2<- AA
3095    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3096    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3097    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3098    @ no-op                             @ releasing store
3099    str     r1, [r0, #offStaticField_value] @ field<- vAA
3100    GOTO_OPCODE(ip)                     @ jump to next instruction
3101
3102
3103/* ------------------------------ */
3104    .balign 64
3105.L_OP_SPUT_BYTE: /* 0x6b */
3106/* File: armv5te/OP_SPUT_BYTE.S */
3107/* File: armv5te/OP_SPUT.S */
3108    /*
3109     * General 32-bit SPUT handler.
3110     *
3111     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3112     */
3113    /* op vAA, field@BBBB */
3114    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3115    FETCH(r1, 1)                        @ r1<- field ref BBBB
3116    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3117    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3118    cmp     r0, #0                      @ is resolved entry null?
3119    beq     .LOP_SPUT_BYTE_resolve         @ yes, do resolve
3120.LOP_SPUT_BYTE_finish:   @ field ptr in r0
3121    mov     r2, rINST, lsr #8           @ r2<- AA
3122    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3123    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3124    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3125    @ no-op                             @ releasing store
3126    str     r1, [r0, #offStaticField_value] @ field<- vAA
3127    GOTO_OPCODE(ip)                     @ jump to next instruction
3128
3129
3130/* ------------------------------ */
3131    .balign 64
3132.L_OP_SPUT_CHAR: /* 0x6c */
3133/* File: armv5te/OP_SPUT_CHAR.S */
3134/* File: armv5te/OP_SPUT.S */
3135    /*
3136     * General 32-bit SPUT handler.
3137     *
3138     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3139     */
3140    /* op vAA, field@BBBB */
3141    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3142    FETCH(r1, 1)                        @ r1<- field ref BBBB
3143    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3144    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3145    cmp     r0, #0                      @ is resolved entry null?
3146    beq     .LOP_SPUT_CHAR_resolve         @ yes, do resolve
3147.LOP_SPUT_CHAR_finish:   @ field ptr in r0
3148    mov     r2, rINST, lsr #8           @ r2<- AA
3149    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3150    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3152    @ no-op                             @ releasing store
3153    str     r1, [r0, #offStaticField_value] @ field<- vAA
3154    GOTO_OPCODE(ip)                     @ jump to next instruction
3155
3156
3157/* ------------------------------ */
3158    .balign 64
3159.L_OP_SPUT_SHORT: /* 0x6d */
3160/* File: armv5te/OP_SPUT_SHORT.S */
3161/* File: armv5te/OP_SPUT.S */
3162    /*
3163     * General 32-bit SPUT handler.
3164     *
3165     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
3166     */
3167    /* op vAA, field@BBBB */
3168    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
3169    FETCH(r1, 1)                        @ r1<- field ref BBBB
3170    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
3171    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
3172    cmp     r0, #0                      @ is resolved entry null?
3173    beq     .LOP_SPUT_SHORT_resolve         @ yes, do resolve
3174.LOP_SPUT_SHORT_finish:   @ field ptr in r0
3175    mov     r2, rINST, lsr #8           @ r2<- AA
3176    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
3177    GET_VREG(r1, r2)                    @ r1<- fp[AA]
3178    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3179    @ no-op                             @ releasing store
3180    str     r1, [r0, #offStaticField_value] @ field<- vAA
3181    GOTO_OPCODE(ip)                     @ jump to next instruction
3182
3183
3184/* ------------------------------ */
3185    .balign 64
3186.L_OP_INVOKE_VIRTUAL: /* 0x6e */
3187/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3188    /*
3189     * Handle a virtual method call.
3190     *
3191     * for: invoke-virtual, invoke-virtual/range
3192     */
3193    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3194    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3195    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3196    FETCH(r1, 1)                        @ r1<- BBBB
3197    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3198    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3199    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3200    .if     (!0)
3201    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3202    .endif
3203    cmp     r0, #0                      @ already resolved?
3204    EXPORT_PC()                         @ must export for invoke
3205    bne     .LOP_INVOKE_VIRTUAL_continue        @ yes, continue on
3206    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3207    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3208    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3209    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3210    cmp     r0, #0                      @ got null?
3211    bne     .LOP_INVOKE_VIRTUAL_continue        @ no, continue
3212    b       common_exceptionThrown      @ yes, handle exception
3213
3214/* ------------------------------ */
3215    .balign 64
3216.L_OP_INVOKE_SUPER: /* 0x6f */
3217/* File: armv5te/OP_INVOKE_SUPER.S */
3218    /*
3219     * Handle a "super" method call.
3220     *
3221     * for: invoke-super, invoke-super/range
3222     */
3223    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3224    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3225    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3226    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3227    .if     (!0)
3228    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3229    .endif
3230    FETCH(r1, 1)                        @ r1<- BBBB
3231    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3232    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3233    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3234    cmp     r2, #0                      @ null "this"?
3235    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3236    beq     common_errNullObject        @ null "this", throw exception
3237    cmp     r0, #0                      @ already resolved?
3238    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3239    EXPORT_PC()                         @ must export for invoke
3240    bne     .LOP_INVOKE_SUPER_continue        @ resolved, continue on
3241    b       .LOP_INVOKE_SUPER_resolve         @ do resolve now
3242
3243/* ------------------------------ */
3244    .balign 64
3245.L_OP_INVOKE_DIRECT: /* 0x70 */
3246/* File: armv5te/OP_INVOKE_DIRECT.S */
3247    /*
3248     * Handle a direct method call.
3249     *
3250     * (We could defer the "is 'this' pointer null" test to the common
3251     * method invocation code, and use a flag to indicate that static
3252     * calls don't count.  If we do this as part of copying the arguments
3253     * out we could avoiding loading the first arg twice.)
3254     *
3255     * for: invoke-direct, invoke-direct/range
3256     */
3257    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3258    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3259    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3260    FETCH(r1, 1)                        @ r1<- BBBB
3261    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3262    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3263    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3264    .if     (!0)
3265    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3266    .endif
3267    cmp     r0, #0                      @ already resolved?
3268    EXPORT_PC()                         @ must export for invoke
3269    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3270    beq     .LOP_INVOKE_DIRECT_resolve         @ not resolved, do it now
3271.LOP_INVOKE_DIRECT_finish:
3272    cmp     r2, #0                      @ null "this" ref?
3273    bne     common_invokeMethodNoRange   @ no, continue on
3274    b       common_errNullObject        @ yes, throw exception
3275
3276/* ------------------------------ */
3277    .balign 64
3278.L_OP_INVOKE_STATIC: /* 0x71 */
3279/* File: armv5te/OP_INVOKE_STATIC.S */
3280    /*
3281     * Handle a static method call.
3282     *
3283     * for: invoke-static, invoke-static/range
3284     */
3285    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3286    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3287    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3288    FETCH(r1, 1)                        @ r1<- BBBB
3289    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3290    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3291    cmp     r0, #0                      @ already resolved?
3292    EXPORT_PC()                         @ must export for invoke
3293    bne     common_invokeMethodNoRange @ yes, continue on
32940:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3295    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3296    mov     r2, #METHOD_STATIC          @ resolver method type
3297    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3298    cmp     r0, #0                      @ got null?
3299    bne     common_invokeMethodNoRange @ no, continue
3300    b       common_exceptionThrown      @ yes, handle exception
3301
3302/* ------------------------------ */
3303    .balign 64
3304.L_OP_INVOKE_INTERFACE: /* 0x72 */
3305/* File: armv5te/OP_INVOKE_INTERFACE.S */
3306    /*
3307     * Handle an interface method call.
3308     *
3309     * for: invoke-interface, invoke-interface/range
3310     */
3311    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3312    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3313    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3314    FETCH(r1, 1)                        @ r1<- BBBB
3315    .if     (!0)
3316    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3317    .endif
3318    EXPORT_PC()                         @ must export for invoke
3319    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3320    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3321    cmp     r0, #0                      @ null obj?
3322    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3323    beq     common_errNullObject        @ yes, fail
3324    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3325    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3326    cmp     r0, #0                      @ failed?
3327    beq     common_exceptionThrown      @ yes, handle exception
3328    b       common_invokeMethodNoRange @ jump to common handler
3329
3330/* ------------------------------ */
3331    .balign 64
3332.L_OP_UNUSED_73: /* 0x73 */
3333/* File: armv5te/OP_UNUSED_73.S */
3334/* File: armv5te/unused.S */
3335    bl      common_abort
3336
3337
3338/* ------------------------------ */
3339    .balign 64
3340.L_OP_INVOKE_VIRTUAL_RANGE: /* 0x74 */
3341/* File: armv5te/OP_INVOKE_VIRTUAL_RANGE.S */
3342/* File: armv5te/OP_INVOKE_VIRTUAL.S */
3343    /*
3344     * Handle a virtual method call.
3345     *
3346     * for: invoke-virtual, invoke-virtual/range
3347     */
3348    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3349    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3350    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3351    FETCH(r1, 1)                        @ r1<- BBBB
3352    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3353    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3354    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3355    .if     (!1)
3356    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3357    .endif
3358    cmp     r0, #0                      @ already resolved?
3359    EXPORT_PC()                         @ must export for invoke
3360    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ yes, continue on
3361    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3362    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3363    mov     r2, #METHOD_VIRTUAL         @ resolver method type
3364    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3365    cmp     r0, #0                      @ got null?
3366    bne     .LOP_INVOKE_VIRTUAL_RANGE_continue        @ no, continue
3367    b       common_exceptionThrown      @ yes, handle exception
3368
3369
3370/* ------------------------------ */
3371    .balign 64
3372.L_OP_INVOKE_SUPER_RANGE: /* 0x75 */
3373/* File: armv5te/OP_INVOKE_SUPER_RANGE.S */
3374/* File: armv5te/OP_INVOKE_SUPER.S */
3375    /*
3376     * Handle a "super" method call.
3377     *
3378     * for: invoke-super, invoke-super/range
3379     */
3380    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3381    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3382    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3383    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3384    .if     (!1)
3385    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3386    .endif
3387    FETCH(r1, 1)                        @ r1<- BBBB
3388    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3389    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3390    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved baseMethod
3391    cmp     r2, #0                      @ null "this"?
3392    ldr     r9, [rGLUE, #offGlue_method] @ r9<- current method
3393    beq     common_errNullObject        @ null "this", throw exception
3394    cmp     r0, #0                      @ already resolved?
3395    ldr     r9, [r9, #offMethod_clazz]  @ r9<- method->clazz
3396    EXPORT_PC()                         @ must export for invoke
3397    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ resolved, continue on
3398    b       .LOP_INVOKE_SUPER_RANGE_resolve         @ do resolve now
3399
3400
3401/* ------------------------------ */
3402    .balign 64
3403.L_OP_INVOKE_DIRECT_RANGE: /* 0x76 */
3404/* File: armv5te/OP_INVOKE_DIRECT_RANGE.S */
3405/* File: armv5te/OP_INVOKE_DIRECT.S */
3406    /*
3407     * Handle a direct method call.
3408     *
3409     * (We could defer the "is 'this' pointer null" test to the common
3410     * method invocation code, and use a flag to indicate that static
3411     * calls don't count.  If we do this as part of copying the arguments
3412     * out we could avoiding loading the first arg twice.)
3413     *
3414     * for: invoke-direct, invoke-direct/range
3415     */
3416    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3417    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3418    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3419    FETCH(r1, 1)                        @ r1<- BBBB
3420    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3421    FETCH(r10, 2)                       @ r10<- GFED or CCCC
3422    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3423    .if     (!1)
3424    and     r10, r10, #15               @ r10<- D (or stays CCCC)
3425    .endif
3426    cmp     r0, #0                      @ already resolved?
3427    EXPORT_PC()                         @ must export for invoke
3428    GET_VREG(r2, r10)                   @ r2<- "this" ptr
3429    beq     .LOP_INVOKE_DIRECT_RANGE_resolve         @ not resolved, do it now
3430.LOP_INVOKE_DIRECT_RANGE_finish:
3431    cmp     r2, #0                      @ null "this" ref?
3432    bne     common_invokeMethodRange   @ no, continue on
3433    b       common_errNullObject        @ yes, throw exception
3434
3435
3436/* ------------------------------ */
3437    .balign 64
3438.L_OP_INVOKE_STATIC_RANGE: /* 0x77 */
3439/* File: armv5te/OP_INVOKE_STATIC_RANGE.S */
3440/* File: armv5te/OP_INVOKE_STATIC.S */
3441    /*
3442     * Handle a static method call.
3443     *
3444     * for: invoke-static, invoke-static/range
3445     */
3446    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3447    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3448    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- pDvmDex
3449    FETCH(r1, 1)                        @ r1<- BBBB
3450    ldr     r3, [r3, #offDvmDex_pResMethods]    @ r3<- pDvmDex->pResMethods
3451    ldr     r0, [r3, r1, lsl #2]        @ r0<- resolved methodToCall
3452    cmp     r0, #0                      @ already resolved?
3453    EXPORT_PC()                         @ must export for invoke
3454    bne     common_invokeMethodRange @ yes, continue on
34550:  ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
3456    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
3457    mov     r2, #METHOD_STATIC          @ resolver method type
3458    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
3459    cmp     r0, #0                      @ got null?
3460    bne     common_invokeMethodRange @ no, continue
3461    b       common_exceptionThrown      @ yes, handle exception
3462
3463
3464/* ------------------------------ */
3465    .balign 64
3466.L_OP_INVOKE_INTERFACE_RANGE: /* 0x78 */
3467/* File: armv5te/OP_INVOKE_INTERFACE_RANGE.S */
3468/* File: armv5te/OP_INVOKE_INTERFACE.S */
3469    /*
3470     * Handle an interface method call.
3471     *
3472     * for: invoke-interface, invoke-interface/range
3473     */
3474    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
3475    /* op {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
3476    FETCH(r2, 2)                        @ r2<- FEDC or CCCC
3477    FETCH(r1, 1)                        @ r1<- BBBB
3478    .if     (!1)
3479    and     r2, r2, #15                 @ r2<- C (or stays CCCC)
3480    .endif
3481    EXPORT_PC()                         @ must export for invoke
3482    GET_VREG(r0, r2)                    @ r0<- first arg ("this")
3483    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- methodClassDex
3484    cmp     r0, #0                      @ null obj?
3485    ldr     r2, [rGLUE, #offGlue_method]  @ r2<- method
3486    beq     common_errNullObject        @ yes, fail
3487    ldr     r0, [r0, #offObject_clazz]  @ r0<- thisPtr->clazz
3488    bl      dvmFindInterfaceMethodInCache @ r0<- call(class, ref, method, dex)
3489    cmp     r0, #0                      @ failed?
3490    beq     common_exceptionThrown      @ yes, handle exception
3491    b       common_invokeMethodRange @ jump to common handler
3492
3493
3494/* ------------------------------ */
3495    .balign 64
3496.L_OP_UNUSED_79: /* 0x79 */
3497/* File: armv5te/OP_UNUSED_79.S */
3498/* File: armv5te/unused.S */
3499    bl      common_abort
3500
3501
3502/* ------------------------------ */
3503    .balign 64
3504.L_OP_UNUSED_7A: /* 0x7a */
3505/* File: armv5te/OP_UNUSED_7A.S */
3506/* File: armv5te/unused.S */
3507    bl      common_abort
3508
3509
3510/* ------------------------------ */
3511    .balign 64
3512.L_OP_NEG_INT: /* 0x7b */
3513/* File: armv5te/OP_NEG_INT.S */
3514/* File: armv5te/unop.S */
3515    /*
3516     * Generic 32-bit unary operation.  Provide an "instr" line that
3517     * specifies an instruction that performs "result = op r0".
3518     * This could be an ARM instruction or a function call.
3519     *
3520     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3521     *      int-to-byte, int-to-char, int-to-short
3522     */
3523    /* unop vA, vB */
3524    mov     r3, rINST, lsr #12          @ r3<- B
3525    mov     r9, rINST, lsr #8           @ r9<- A+
3526    GET_VREG(r0, r3)                    @ r0<- vB
3527    and     r9, r9, #15
3528                               @ optional op; may set condition codes
3529    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3530    rsb     r0, r0, #0                              @ r0<- op, r0-r3 changed
3531    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3532    SET_VREG(r0, r9)                    @ vAA<- r0
3533    GOTO_OPCODE(ip)                     @ jump to next instruction
3534    /* 9-10 instructions */
3535
3536
3537/* ------------------------------ */
3538    .balign 64
3539.L_OP_NOT_INT: /* 0x7c */
3540/* File: armv5te/OP_NOT_INT.S */
3541/* File: armv5te/unop.S */
3542    /*
3543     * Generic 32-bit unary operation.  Provide an "instr" line that
3544     * specifies an instruction that performs "result = op r0".
3545     * This could be an ARM instruction or a function call.
3546     *
3547     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3548     *      int-to-byte, int-to-char, int-to-short
3549     */
3550    /* unop vA, vB */
3551    mov     r3, rINST, lsr #12          @ r3<- B
3552    mov     r9, rINST, lsr #8           @ r9<- A+
3553    GET_VREG(r0, r3)                    @ r0<- vB
3554    and     r9, r9, #15
3555                               @ optional op; may set condition codes
3556    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3557    mvn     r0, r0                              @ r0<- op, r0-r3 changed
3558    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3559    SET_VREG(r0, r9)                    @ vAA<- r0
3560    GOTO_OPCODE(ip)                     @ jump to next instruction
3561    /* 9-10 instructions */
3562
3563
3564/* ------------------------------ */
3565    .balign 64
3566.L_OP_NEG_LONG: /* 0x7d */
3567/* File: armv5te/OP_NEG_LONG.S */
3568/* File: armv5te/unopWide.S */
3569    /*
3570     * Generic 64-bit unary operation.  Provide an "instr" line that
3571     * specifies an instruction that performs "result = op r0/r1".
3572     * This could be an ARM instruction or a function call.
3573     *
3574     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3575     */
3576    /* unop vA, vB */
3577    mov     r9, rINST, lsr #8           @ r9<- A+
3578    mov     r3, rINST, lsr #12          @ r3<- B
3579    and     r9, r9, #15
3580    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3581    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3582    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3583    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3584    rsbs    r0, r0, #0                           @ optional op; may set condition codes
3585    rsc     r1, r1, #0                              @ r0/r1<- op, r2-r3 changed
3586    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3587    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3588    GOTO_OPCODE(ip)                     @ jump to next instruction
3589    /* 12-13 instructions */
3590
3591
3592/* ------------------------------ */
3593    .balign 64
3594.L_OP_NOT_LONG: /* 0x7e */
3595/* File: armv5te/OP_NOT_LONG.S */
3596/* File: armv5te/unopWide.S */
3597    /*
3598     * Generic 64-bit unary operation.  Provide an "instr" line that
3599     * specifies an instruction that performs "result = op r0/r1".
3600     * This could be an ARM instruction or a function call.
3601     *
3602     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3603     */
3604    /* unop vA, vB */
3605    mov     r9, rINST, lsr #8           @ r9<- A+
3606    mov     r3, rINST, lsr #12          @ r3<- B
3607    and     r9, r9, #15
3608    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3609    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3610    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3611    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3612    mvn     r0, r0                           @ optional op; may set condition codes
3613    mvn     r1, r1                              @ r0/r1<- op, r2-r3 changed
3614    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3615    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3616    GOTO_OPCODE(ip)                     @ jump to next instruction
3617    /* 12-13 instructions */
3618
3619
3620/* ------------------------------ */
3621    .balign 64
3622.L_OP_NEG_FLOAT: /* 0x7f */
3623/* File: armv5te/OP_NEG_FLOAT.S */
3624/* File: armv5te/unop.S */
3625    /*
3626     * Generic 32-bit unary operation.  Provide an "instr" line that
3627     * specifies an instruction that performs "result = op r0".
3628     * This could be an ARM instruction or a function call.
3629     *
3630     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3631     *      int-to-byte, int-to-char, int-to-short
3632     */
3633    /* unop vA, vB */
3634    mov     r3, rINST, lsr #12          @ r3<- B
3635    mov     r9, rINST, lsr #8           @ r9<- A+
3636    GET_VREG(r0, r3)                    @ r0<- vB
3637    and     r9, r9, #15
3638                               @ optional op; may set condition codes
3639    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3640    add     r0, r0, #0x80000000                              @ r0<- op, r0-r3 changed
3641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3642    SET_VREG(r0, r9)                    @ vAA<- r0
3643    GOTO_OPCODE(ip)                     @ jump to next instruction
3644    /* 9-10 instructions */
3645
3646
3647/* ------------------------------ */
3648    .balign 64
3649.L_OP_NEG_DOUBLE: /* 0x80 */
3650/* File: armv5te/OP_NEG_DOUBLE.S */
3651/* File: armv5te/unopWide.S */
3652    /*
3653     * Generic 64-bit unary operation.  Provide an "instr" line that
3654     * specifies an instruction that performs "result = op r0/r1".
3655     * This could be an ARM instruction or a function call.
3656     *
3657     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3658     */
3659    /* unop vA, vB */
3660    mov     r9, rINST, lsr #8           @ r9<- A+
3661    mov     r3, rINST, lsr #12          @ r3<- B
3662    and     r9, r9, #15
3663    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3664    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3665    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3666    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3667                               @ optional op; may set condition codes
3668    add     r1, r1, #0x80000000                              @ r0/r1<- op, r2-r3 changed
3669    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3670    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3671    GOTO_OPCODE(ip)                     @ jump to next instruction
3672    /* 12-13 instructions */
3673
3674
3675/* ------------------------------ */
3676    .balign 64
3677.L_OP_INT_TO_LONG: /* 0x81 */
3678/* File: armv5te/OP_INT_TO_LONG.S */
3679/* File: armv5te/unopWider.S */
3680    /*
3681     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3682     * that specifies an instruction that performs "result = op r0", where
3683     * "result" is a 64-bit quantity in r0/r1.
3684     *
3685     * For: int-to-long, int-to-double, float-to-long, float-to-double
3686     */
3687    /* unop vA, vB */
3688    mov     r9, rINST, lsr #8           @ r9<- A+
3689    mov     r3, rINST, lsr #12          @ r3<- B
3690    and     r9, r9, #15
3691    GET_VREG(r0, r3)                    @ r0<- vB
3692    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3693                               @ optional op; may set condition codes
3694    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3695    mov     r1, r0, asr #31                              @ r0<- op, r0-r3 changed
3696    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3697    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3698    GOTO_OPCODE(ip)                     @ jump to next instruction
3699    /* 10-11 instructions */
3700
3701
3702/* ------------------------------ */
3703    .balign 64
3704.L_OP_INT_TO_FLOAT: /* 0x82 */
3705/* File: armv5te/OP_INT_TO_FLOAT.S */
3706/* File: armv5te/unop.S */
3707    /*
3708     * Generic 32-bit unary operation.  Provide an "instr" line that
3709     * specifies an instruction that performs "result = op r0".
3710     * This could be an ARM instruction or a function call.
3711     *
3712     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3713     *      int-to-byte, int-to-char, int-to-short
3714     */
3715    /* unop vA, vB */
3716    mov     r3, rINST, lsr #12          @ r3<- B
3717    mov     r9, rINST, lsr #8           @ r9<- A+
3718    GET_VREG(r0, r3)                    @ r0<- vB
3719    and     r9, r9, #15
3720                               @ optional op; may set condition codes
3721    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3722    bl      __aeabi_i2f                              @ r0<- op, r0-r3 changed
3723    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3724    SET_VREG(r0, r9)                    @ vAA<- r0
3725    GOTO_OPCODE(ip)                     @ jump to next instruction
3726    /* 9-10 instructions */
3727
3728
3729/* ------------------------------ */
3730    .balign 64
3731.L_OP_INT_TO_DOUBLE: /* 0x83 */
3732/* File: armv5te/OP_INT_TO_DOUBLE.S */
3733/* File: armv5te/unopWider.S */
3734    /*
3735     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3736     * that specifies an instruction that performs "result = op r0", where
3737     * "result" is a 64-bit quantity in r0/r1.
3738     *
3739     * For: int-to-long, int-to-double, float-to-long, float-to-double
3740     */
3741    /* unop vA, vB */
3742    mov     r9, rINST, lsr #8           @ r9<- A+
3743    mov     r3, rINST, lsr #12          @ r3<- B
3744    and     r9, r9, #15
3745    GET_VREG(r0, r3)                    @ r0<- vB
3746    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3747                               @ optional op; may set condition codes
3748    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3749    bl      __aeabi_i2d                              @ r0<- op, r0-r3 changed
3750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3751    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3752    GOTO_OPCODE(ip)                     @ jump to next instruction
3753    /* 10-11 instructions */
3754
3755
3756/* ------------------------------ */
3757    .balign 64
3758.L_OP_LONG_TO_INT: /* 0x84 */
3759/* File: armv5te/OP_LONG_TO_INT.S */
3760/* we ignore the high word, making this equivalent to a 32-bit reg move */
3761/* File: armv5te/OP_MOVE.S */
3762    /* for move, move-object, long-to-int */
3763    /* op vA, vB */
3764    mov     r1, rINST, lsr #12          @ r1<- B from 15:12
3765    mov     r0, rINST, lsr #8           @ r0<- A from 11:8
3766    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3767    GET_VREG(r2, r1)                    @ r2<- fp[B]
3768    and     r0, r0, #15
3769    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
3770    SET_VREG(r2, r0)                    @ fp[A]<- r2
3771    GOTO_OPCODE(ip)                     @ execute next instruction
3772
3773
3774/* ------------------------------ */
3775    .balign 64
3776.L_OP_LONG_TO_FLOAT: /* 0x85 */
3777/* File: armv5te/OP_LONG_TO_FLOAT.S */
3778/* File: armv5te/unopNarrower.S */
3779    /*
3780     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3781     * that specifies an instruction that performs "result = op r0/r1", where
3782     * "result" is a 32-bit quantity in r0.
3783     *
3784     * For: long-to-float, double-to-int, double-to-float
3785     *
3786     * (This would work for long-to-int, but that instruction is actually
3787     * an exact match for OP_MOVE.)
3788     */
3789    /* unop vA, vB */
3790    mov     r3, rINST, lsr #12          @ r3<- B
3791    mov     r9, rINST, lsr #8           @ r9<- A+
3792    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3793    and     r9, r9, #15
3794    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3795    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3796                               @ optional op; may set condition codes
3797    bl      __aeabi_l2f                              @ r0<- op, r0-r3 changed
3798    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3799    SET_VREG(r0, r9)                    @ vA<- r0
3800    GOTO_OPCODE(ip)                     @ jump to next instruction
3801    /* 10-11 instructions */
3802
3803
3804/* ------------------------------ */
3805    .balign 64
3806.L_OP_LONG_TO_DOUBLE: /* 0x86 */
3807/* File: armv5te/OP_LONG_TO_DOUBLE.S */
3808/* File: armv5te/unopWide.S */
3809    /*
3810     * Generic 64-bit unary operation.  Provide an "instr" line that
3811     * specifies an instruction that performs "result = op r0/r1".
3812     * This could be an ARM instruction or a function call.
3813     *
3814     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
3815     */
3816    /* unop vA, vB */
3817    mov     r9, rINST, lsr #8           @ r9<- A+
3818    mov     r3, rINST, lsr #12          @ r3<- B
3819    and     r9, r9, #15
3820    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3821    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3822    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
3823    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3824                               @ optional op; may set condition codes
3825    bl      __aeabi_l2d                              @ r0/r1<- op, r2-r3 changed
3826    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3827    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
3828    GOTO_OPCODE(ip)                     @ jump to next instruction
3829    /* 12-13 instructions */
3830
3831
3832/* ------------------------------ */
3833    .balign 64
3834.L_OP_FLOAT_TO_INT: /* 0x87 */
3835/* File: armv5te/OP_FLOAT_TO_INT.S */
3836/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3837/* File: armv5te/unop.S */
3838    /*
3839     * Generic 32-bit unary operation.  Provide an "instr" line that
3840     * specifies an instruction that performs "result = op r0".
3841     * This could be an ARM instruction or a function call.
3842     *
3843     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
3844     *      int-to-byte, int-to-char, int-to-short
3845     */
3846    /* unop vA, vB */
3847    mov     r3, rINST, lsr #12          @ r3<- B
3848    mov     r9, rINST, lsr #8           @ r9<- A+
3849    GET_VREG(r0, r3)                    @ r0<- vB
3850    and     r9, r9, #15
3851                               @ optional op; may set condition codes
3852    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3853    bl      __aeabi_f2iz                              @ r0<- op, r0-r3 changed
3854    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3855    SET_VREG(r0, r9)                    @ vAA<- r0
3856    GOTO_OPCODE(ip)                     @ jump to next instruction
3857    /* 9-10 instructions */
3858
3859
3860#if 0
3861@include "armv5te/unop.S" {"instr":"bl      f2i_doconv"}
3862@break
3863/*
3864 * Convert the float in r0 to an int in r0.
3865 *
3866 * We have to clip values to int min/max per the specification.  The
3867 * expected common case is a "reasonable" value that converts directly
3868 * to modest integer.  The EABI convert function isn't doing this for us.
3869 */
3870f2i_doconv:
3871    stmfd   sp!, {r4, lr}
3872    mov     r1, #0x4f000000             @ (float)maxint
3873    mov     r4, r0
3874    bl      __aeabi_fcmpge              @ is arg >= maxint?
3875    cmp     r0, #0                      @ nonzero == yes
3876    mvnne   r0, #0x80000000             @ return maxint (7fffffff)
3877    ldmnefd sp!, {r4, pc}
3878
3879    mov     r0, r4                      @ recover arg
3880    mov     r1, #0xcf000000             @ (float)minint
3881    bl      __aeabi_fcmple              @ is arg <= minint?
3882    cmp     r0, #0                      @ nonzero == yes
3883    movne   r0, #0x80000000             @ return minint (80000000)
3884    ldmnefd sp!, {r4, pc}
3885
3886    mov     r0, r4                      @ recover arg
3887    mov     r1, r4
3888    bl      __aeabi_fcmpeq              @ is arg == self?
3889    cmp     r0, #0                      @ zero == no
3890    ldmeqfd sp!, {r4, pc}               @ return zero for NaN
3891
3892    mov     r0, r4                      @ recover arg
3893    bl      __aeabi_f2iz                @ convert float to int
3894    ldmfd   sp!, {r4, pc}
3895#endif
3896
3897/* ------------------------------ */
3898    .balign 64
3899.L_OP_FLOAT_TO_LONG: /* 0x88 */
3900/* File: armv5te/OP_FLOAT_TO_LONG.S */
3901@include "armv5te/unopWider.S" {"instr":"bl      __aeabi_f2lz"}
3902/* File: armv5te/unopWider.S */
3903    /*
3904     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3905     * that specifies an instruction that performs "result = op r0", where
3906     * "result" is a 64-bit quantity in r0/r1.
3907     *
3908     * For: int-to-long, int-to-double, float-to-long, float-to-double
3909     */
3910    /* unop vA, vB */
3911    mov     r9, rINST, lsr #8           @ r9<- A+
3912    mov     r3, rINST, lsr #12          @ r3<- B
3913    and     r9, r9, #15
3914    GET_VREG(r0, r3)                    @ r0<- vB
3915    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3916                               @ optional op; may set condition codes
3917    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3918    bl      f2l_doconv                              @ r0<- op, r0-r3 changed
3919    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3920    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3921    GOTO_OPCODE(ip)                     @ jump to next instruction
3922    /* 10-11 instructions */
3923
3924
3925
3926/* ------------------------------ */
3927    .balign 64
3928.L_OP_FLOAT_TO_DOUBLE: /* 0x89 */
3929/* File: armv5te/OP_FLOAT_TO_DOUBLE.S */
3930/* File: armv5te/unopWider.S */
3931    /*
3932     * Generic 32bit-to-64bit unary operation.  Provide an "instr" line
3933     * that specifies an instruction that performs "result = op r0", where
3934     * "result" is a 64-bit quantity in r0/r1.
3935     *
3936     * For: int-to-long, int-to-double, float-to-long, float-to-double
3937     */
3938    /* unop vA, vB */
3939    mov     r9, rINST, lsr #8           @ r9<- A+
3940    mov     r3, rINST, lsr #12          @ r3<- B
3941    and     r9, r9, #15
3942    GET_VREG(r0, r3)                    @ r0<- vB
3943    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
3944                               @ optional op; may set condition codes
3945    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3946    bl      __aeabi_f2d                              @ r0<- op, r0-r3 changed
3947    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3948    stmia   r9, {r0-r1}                 @ vA/vA+1<- r0/r1
3949    GOTO_OPCODE(ip)                     @ jump to next instruction
3950    /* 10-11 instructions */
3951
3952
3953/* ------------------------------ */
3954    .balign 64
3955.L_OP_DOUBLE_TO_INT: /* 0x8a */
3956/* File: armv5te/OP_DOUBLE_TO_INT.S */
3957/* EABI appears to have Java-style conversions of +inf/-inf/NaN */
3958/* File: armv5te/unopNarrower.S */
3959    /*
3960     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
3961     * that specifies an instruction that performs "result = op r0/r1", where
3962     * "result" is a 32-bit quantity in r0.
3963     *
3964     * For: long-to-float, double-to-int, double-to-float
3965     *
3966     * (This would work for long-to-int, but that instruction is actually
3967     * an exact match for OP_MOVE.)
3968     */
3969    /* unop vA, vB */
3970    mov     r3, rINST, lsr #12          @ r3<- B
3971    mov     r9, rINST, lsr #8           @ r9<- A+
3972    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
3973    and     r9, r9, #15
3974    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
3975    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
3976                               @ optional op; may set condition codes
3977    bl      __aeabi_d2iz                              @ r0<- op, r0-r3 changed
3978    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
3979    SET_VREG(r0, r9)                    @ vA<- r0
3980    GOTO_OPCODE(ip)                     @ jump to next instruction
3981    /* 10-11 instructions */
3982
3983
3984#if 0
3985@include "armv5te/unopNarrower.S" {"instr":"bl      d2i_doconv"}
3986@break
3987/*
3988 * Convert the double in r0/r1 to an int in r0.
3989 *
3990 * We have to clip values to int min/max per the specification.  The
3991 * expected common case is a "reasonable" value that converts directly
3992 * to modest integer.  The EABI convert function isn't doing this for us.
3993 */
3994d2i_doconv:
3995    stmfd   sp!, {r4, r5, lr}           @ save regs
3996    mov     r2, #0x80000000             @ maxint, as a double (low word)
3997    mov     r2, r2, asr #9              @  0xffc00000
3998    sub     sp, sp, #4                  @ align for EABI
3999    mvn     r3, #0xbe000000             @ maxint, as a double (high word)
4000    sub     r3, r3, #0x00200000         @  0x41dfffff
4001    mov     r4, r0                      @ save a copy of r0
4002    mov     r5, r1                      @  and r1
4003    bl      __aeabi_dcmpge              @ is arg >= maxint?
4004    cmp     r0, #0                      @ nonzero == yes
4005    mvnne   r0, #0x80000000             @ return maxint (0x7fffffff)
4006    bne     1f
4007
4008    mov     r0, r4                      @ recover arg
4009    mov     r1, r5
4010    mov     r3, #0xc1000000             @ minint, as a double (high word)
4011    add     r3, r3, #0x00e00000         @  0xc1e00000
4012    mov     r2, #0                      @ minint, as a double (low word)
4013    bl      __aeabi_dcmple              @ is arg <= minint?
4014    cmp     r0, #0                      @ nonzero == yes
4015    movne   r0, #0x80000000             @ return minint (80000000)
4016    bne     1f
4017
4018    mov     r0, r4                      @ recover arg
4019    mov     r1, r5
4020    mov     r2, r4                      @ compare against self
4021    mov     r3, r5
4022    bl      __aeabi_dcmpeq              @ is arg == self?
4023    cmp     r0, #0                      @ zero == no
4024    beq     1f                          @ return zero for NaN
4025
4026    mov     r0, r4                      @ recover arg
4027    mov     r1, r5
4028    bl      __aeabi_d2iz                @ convert double to int
4029
40301:
4031    add     sp, sp, #4
4032    ldmfd   sp!, {r4, r5, pc}
4033#endif
4034
4035/* ------------------------------ */
4036    .balign 64
4037.L_OP_DOUBLE_TO_LONG: /* 0x8b */
4038/* File: armv5te/OP_DOUBLE_TO_LONG.S */
4039@include "armv5te/unopWide.S" {"instr":"bl      __aeabi_d2lz"}
4040/* File: armv5te/unopWide.S */
4041    /*
4042     * Generic 64-bit unary operation.  Provide an "instr" line that
4043     * specifies an instruction that performs "result = op r0/r1".
4044     * This could be an ARM instruction or a function call.
4045     *
4046     * For: neg-long, not-long, neg-double, long-to-double, double-to-long
4047     */
4048    /* unop vA, vB */
4049    mov     r9, rINST, lsr #8           @ r9<- A+
4050    mov     r3, rINST, lsr #12          @ r3<- B
4051    and     r9, r9, #15
4052    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4053    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
4054    ldmia   r3, {r0-r1}                 @ r0/r1<- vAA
4055    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4056                               @ optional op; may set condition codes
4057    bl      d2l_doconv                              @ r0/r1<- op, r2-r3 changed
4058    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4059    stmia   r9, {r0-r1}                 @ vAA<- r0/r1
4060    GOTO_OPCODE(ip)                     @ jump to next instruction
4061    /* 12-13 instructions */
4062
4063
4064
4065/* ------------------------------ */
4066    .balign 64
4067.L_OP_DOUBLE_TO_FLOAT: /* 0x8c */
4068/* File: armv5te/OP_DOUBLE_TO_FLOAT.S */
4069/* File: armv5te/unopNarrower.S */
4070    /*
4071     * Generic 64bit-to-32bit unary operation.  Provide an "instr" line
4072     * that specifies an instruction that performs "result = op r0/r1", where
4073     * "result" is a 32-bit quantity in r0.
4074     *
4075     * For: long-to-float, double-to-int, double-to-float
4076     *
4077     * (This would work for long-to-int, but that instruction is actually
4078     * an exact match for OP_MOVE.)
4079     */
4080    /* unop vA, vB */
4081    mov     r3, rINST, lsr #12          @ r3<- B
4082    mov     r9, rINST, lsr #8           @ r9<- A+
4083    add     r3, rFP, r3, lsl #2         @ r3<- &fp[B]
4084    and     r9, r9, #15
4085    ldmia   r3, {r0-r1}                 @ r0/r1<- vB/vB+1
4086    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4087                               @ optional op; may set condition codes
4088    bl      __aeabi_d2f                              @ r0<- op, r0-r3 changed
4089    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4090    SET_VREG(r0, r9)                    @ vA<- r0
4091    GOTO_OPCODE(ip)                     @ jump to next instruction
4092    /* 10-11 instructions */
4093
4094
4095/* ------------------------------ */
4096    .balign 64
4097.L_OP_INT_TO_BYTE: /* 0x8d */
4098/* File: armv5te/OP_INT_TO_BYTE.S */
4099/* File: armv5te/unop.S */
4100    /*
4101     * Generic 32-bit unary operation.  Provide an "instr" line that
4102     * specifies an instruction that performs "result = op r0".
4103     * This could be an ARM instruction or a function call.
4104     *
4105     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4106     *      int-to-byte, int-to-char, int-to-short
4107     */
4108    /* unop vA, vB */
4109    mov     r3, rINST, lsr #12          @ r3<- B
4110    mov     r9, rINST, lsr #8           @ r9<- A+
4111    GET_VREG(r0, r3)                    @ r0<- vB
4112    and     r9, r9, #15
4113    mov     r0, r0, asl #24                           @ optional op; may set condition codes
4114    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4115    mov     r0, r0, asr #24                              @ r0<- op, r0-r3 changed
4116    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4117    SET_VREG(r0, r9)                    @ vAA<- r0
4118    GOTO_OPCODE(ip)                     @ jump to next instruction
4119    /* 9-10 instructions */
4120
4121
4122/* ------------------------------ */
4123    .balign 64
4124.L_OP_INT_TO_CHAR: /* 0x8e */
4125/* File: armv5te/OP_INT_TO_CHAR.S */
4126/* File: armv5te/unop.S */
4127    /*
4128     * Generic 32-bit unary operation.  Provide an "instr" line that
4129     * specifies an instruction that performs "result = op r0".
4130     * This could be an ARM instruction or a function call.
4131     *
4132     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4133     *      int-to-byte, int-to-char, int-to-short
4134     */
4135    /* unop vA, vB */
4136    mov     r3, rINST, lsr #12          @ r3<- B
4137    mov     r9, rINST, lsr #8           @ r9<- A+
4138    GET_VREG(r0, r3)                    @ r0<- vB
4139    and     r9, r9, #15
4140    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4141    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4142    mov     r0, r0, lsr #16                              @ r0<- op, r0-r3 changed
4143    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4144    SET_VREG(r0, r9)                    @ vAA<- r0
4145    GOTO_OPCODE(ip)                     @ jump to next instruction
4146    /* 9-10 instructions */
4147
4148
4149/* ------------------------------ */
4150    .balign 64
4151.L_OP_INT_TO_SHORT: /* 0x8f */
4152/* File: armv5te/OP_INT_TO_SHORT.S */
4153/* File: armv5te/unop.S */
4154    /*
4155     * Generic 32-bit unary operation.  Provide an "instr" line that
4156     * specifies an instruction that performs "result = op r0".
4157     * This could be an ARM instruction or a function call.
4158     *
4159     * for: neg-int, not-int, neg-float, int-to-float, float-to-int,
4160     *      int-to-byte, int-to-char, int-to-short
4161     */
4162    /* unop vA, vB */
4163    mov     r3, rINST, lsr #12          @ r3<- B
4164    mov     r9, rINST, lsr #8           @ r9<- A+
4165    GET_VREG(r0, r3)                    @ r0<- vB
4166    and     r9, r9, #15
4167    mov     r0, r0, asl #16                           @ optional op; may set condition codes
4168    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
4169    mov     r0, r0, asr #16                              @ r0<- op, r0-r3 changed
4170    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4171    SET_VREG(r0, r9)                    @ vAA<- r0
4172    GOTO_OPCODE(ip)                     @ jump to next instruction
4173    /* 9-10 instructions */
4174
4175
4176/* ------------------------------ */
4177    .balign 64
4178.L_OP_ADD_INT: /* 0x90 */
4179/* File: armv5te/OP_ADD_INT.S */
4180/* File: armv5te/binop.S */
4181    /*
4182     * Generic 32-bit binary operation.  Provide an "instr" line that
4183     * specifies an instruction that performs "result = r0 op r1".
4184     * This could be an ARM instruction or a function call.  (If the result
4185     * comes back in a register other than r0, you can override "result".)
4186     *
4187     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4188     * vCC (r1).  Useful for integer division and modulus.  Note that we
4189     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4190     * handles it correctly.
4191     *
4192     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4193     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4194     *      mul-float, div-float, rem-float
4195     */
4196    /* binop vAA, vBB, vCC */
4197    FETCH(r0, 1)                        @ r0<- CCBB
4198    mov     r9, rINST, lsr #8           @ r9<- AA
4199    mov     r3, r0, lsr #8              @ r3<- CC
4200    and     r2, r0, #255                @ r2<- BB
4201    GET_VREG(r1, r3)                    @ r1<- vCC
4202    GET_VREG(r0, r2)                    @ r0<- vBB
4203    .if 0
4204    cmp     r1, #0                      @ is second operand zero?
4205    beq     common_errDivideByZero
4206    .endif
4207
4208    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4209                               @ optional op; may set condition codes
4210    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
4211    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4212    SET_VREG(r0, r9)               @ vAA<- r0
4213    GOTO_OPCODE(ip)                     @ jump to next instruction
4214    /* 11-14 instructions */
4215
4216
4217/* ------------------------------ */
4218    .balign 64
4219.L_OP_SUB_INT: /* 0x91 */
4220/* File: armv5te/OP_SUB_INT.S */
4221/* File: armv5te/binop.S */
4222    /*
4223     * Generic 32-bit binary operation.  Provide an "instr" line that
4224     * specifies an instruction that performs "result = r0 op r1".
4225     * This could be an ARM instruction or a function call.  (If the result
4226     * comes back in a register other than r0, you can override "result".)
4227     *
4228     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4229     * vCC (r1).  Useful for integer division and modulus.  Note that we
4230     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4231     * handles it correctly.
4232     *
4233     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4234     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4235     *      mul-float, div-float, rem-float
4236     */
4237    /* binop vAA, vBB, vCC */
4238    FETCH(r0, 1)                        @ r0<- CCBB
4239    mov     r9, rINST, lsr #8           @ r9<- AA
4240    mov     r3, r0, lsr #8              @ r3<- CC
4241    and     r2, r0, #255                @ r2<- BB
4242    GET_VREG(r1, r3)                    @ r1<- vCC
4243    GET_VREG(r0, r2)                    @ r0<- vBB
4244    .if 0
4245    cmp     r1, #0                      @ is second operand zero?
4246    beq     common_errDivideByZero
4247    .endif
4248
4249    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4250                               @ optional op; may set condition codes
4251    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
4252    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4253    SET_VREG(r0, r9)               @ vAA<- r0
4254    GOTO_OPCODE(ip)                     @ jump to next instruction
4255    /* 11-14 instructions */
4256
4257
4258/* ------------------------------ */
4259    .balign 64
4260.L_OP_MUL_INT: /* 0x92 */
4261/* File: armv5te/OP_MUL_INT.S */
4262/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
4263/* File: armv5te/binop.S */
4264    /*
4265     * Generic 32-bit binary operation.  Provide an "instr" line that
4266     * specifies an instruction that performs "result = r0 op r1".
4267     * This could be an ARM instruction or a function call.  (If the result
4268     * comes back in a register other than r0, you can override "result".)
4269     *
4270     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4271     * vCC (r1).  Useful for integer division and modulus.  Note that we
4272     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4273     * handles it correctly.
4274     *
4275     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4276     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4277     *      mul-float, div-float, rem-float
4278     */
4279    /* binop vAA, vBB, vCC */
4280    FETCH(r0, 1)                        @ r0<- CCBB
4281    mov     r9, rINST, lsr #8           @ r9<- AA
4282    mov     r3, r0, lsr #8              @ r3<- CC
4283    and     r2, r0, #255                @ r2<- BB
4284    GET_VREG(r1, r3)                    @ r1<- vCC
4285    GET_VREG(r0, r2)                    @ r0<- vBB
4286    .if 0
4287    cmp     r1, #0                      @ is second operand zero?
4288    beq     common_errDivideByZero
4289    .endif
4290
4291    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4292                               @ optional op; may set condition codes
4293    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
4294    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4295    SET_VREG(r0, r9)               @ vAA<- r0
4296    GOTO_OPCODE(ip)                     @ jump to next instruction
4297    /* 11-14 instructions */
4298
4299
4300/* ------------------------------ */
4301    .balign 64
4302.L_OP_DIV_INT: /* 0x93 */
4303/* File: armv5te/OP_DIV_INT.S */
4304/* File: armv5te/binop.S */
4305    /*
4306     * Generic 32-bit binary operation.  Provide an "instr" line that
4307     * specifies an instruction that performs "result = r0 op r1".
4308     * This could be an ARM instruction or a function call.  (If the result
4309     * comes back in a register other than r0, you can override "result".)
4310     *
4311     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4312     * vCC (r1).  Useful for integer division and modulus.  Note that we
4313     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4314     * handles it correctly.
4315     *
4316     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4317     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4318     *      mul-float, div-float, rem-float
4319     */
4320    /* binop vAA, vBB, vCC */
4321    FETCH(r0, 1)                        @ r0<- CCBB
4322    mov     r9, rINST, lsr #8           @ r9<- AA
4323    mov     r3, r0, lsr #8              @ r3<- CC
4324    and     r2, r0, #255                @ r2<- BB
4325    GET_VREG(r1, r3)                    @ r1<- vCC
4326    GET_VREG(r0, r2)                    @ r0<- vBB
4327    .if 1
4328    cmp     r1, #0                      @ is second operand zero?
4329    beq     common_errDivideByZero
4330    .endif
4331
4332    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4333                               @ optional op; may set condition codes
4334    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
4335    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4336    SET_VREG(r0, r9)               @ vAA<- r0
4337    GOTO_OPCODE(ip)                     @ jump to next instruction
4338    /* 11-14 instructions */
4339
4340
4341/* ------------------------------ */
4342    .balign 64
4343.L_OP_REM_INT: /* 0x94 */
4344/* File: armv5te/OP_REM_INT.S */
4345/* idivmod returns quotient in r0 and remainder in r1 */
4346/* File: armv5te/binop.S */
4347    /*
4348     * Generic 32-bit binary operation.  Provide an "instr" line that
4349     * specifies an instruction that performs "result = r0 op r1".
4350     * This could be an ARM instruction or a function call.  (If the result
4351     * comes back in a register other than r0, you can override "result".)
4352     *
4353     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4354     * vCC (r1).  Useful for integer division and modulus.  Note that we
4355     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4356     * handles it correctly.
4357     *
4358     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4359     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4360     *      mul-float, div-float, rem-float
4361     */
4362    /* binop vAA, vBB, vCC */
4363    FETCH(r0, 1)                        @ r0<- CCBB
4364    mov     r9, rINST, lsr #8           @ r9<- AA
4365    mov     r3, r0, lsr #8              @ r3<- CC
4366    and     r2, r0, #255                @ r2<- BB
4367    GET_VREG(r1, r3)                    @ r1<- vCC
4368    GET_VREG(r0, r2)                    @ r0<- vBB
4369    .if 1
4370    cmp     r1, #0                      @ is second operand zero?
4371    beq     common_errDivideByZero
4372    .endif
4373
4374    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4375                               @ optional op; may set condition codes
4376    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
4377    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4378    SET_VREG(r1, r9)               @ vAA<- r1
4379    GOTO_OPCODE(ip)                     @ jump to next instruction
4380    /* 11-14 instructions */
4381
4382
4383/* ------------------------------ */
4384    .balign 64
4385.L_OP_AND_INT: /* 0x95 */
4386/* File: armv5te/OP_AND_INT.S */
4387/* File: armv5te/binop.S */
4388    /*
4389     * Generic 32-bit binary operation.  Provide an "instr" line that
4390     * specifies an instruction that performs "result = r0 op r1".
4391     * This could be an ARM instruction or a function call.  (If the result
4392     * comes back in a register other than r0, you can override "result".)
4393     *
4394     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4395     * vCC (r1).  Useful for integer division and modulus.  Note that we
4396     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4397     * handles it correctly.
4398     *
4399     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4400     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4401     *      mul-float, div-float, rem-float
4402     */
4403    /* binop vAA, vBB, vCC */
4404    FETCH(r0, 1)                        @ r0<- CCBB
4405    mov     r9, rINST, lsr #8           @ r9<- AA
4406    mov     r3, r0, lsr #8              @ r3<- CC
4407    and     r2, r0, #255                @ r2<- BB
4408    GET_VREG(r1, r3)                    @ r1<- vCC
4409    GET_VREG(r0, r2)                    @ r0<- vBB
4410    .if 0
4411    cmp     r1, #0                      @ is second operand zero?
4412    beq     common_errDivideByZero
4413    .endif
4414
4415    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4416                               @ optional op; may set condition codes
4417    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
4418    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4419    SET_VREG(r0, r9)               @ vAA<- r0
4420    GOTO_OPCODE(ip)                     @ jump to next instruction
4421    /* 11-14 instructions */
4422
4423
4424/* ------------------------------ */
4425    .balign 64
4426.L_OP_OR_INT: /* 0x96 */
4427/* File: armv5te/OP_OR_INT.S */
4428/* File: armv5te/binop.S */
4429    /*
4430     * Generic 32-bit binary operation.  Provide an "instr" line that
4431     * specifies an instruction that performs "result = r0 op r1".
4432     * This could be an ARM instruction or a function call.  (If the result
4433     * comes back in a register other than r0, you can override "result".)
4434     *
4435     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4436     * vCC (r1).  Useful for integer division and modulus.  Note that we
4437     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4438     * handles it correctly.
4439     *
4440     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4441     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4442     *      mul-float, div-float, rem-float
4443     */
4444    /* binop vAA, vBB, vCC */
4445    FETCH(r0, 1)                        @ r0<- CCBB
4446    mov     r9, rINST, lsr #8           @ r9<- AA
4447    mov     r3, r0, lsr #8              @ r3<- CC
4448    and     r2, r0, #255                @ r2<- BB
4449    GET_VREG(r1, r3)                    @ r1<- vCC
4450    GET_VREG(r0, r2)                    @ r0<- vBB
4451    .if 0
4452    cmp     r1, #0                      @ is second operand zero?
4453    beq     common_errDivideByZero
4454    .endif
4455
4456    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4457                               @ optional op; may set condition codes
4458    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
4459    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4460    SET_VREG(r0, r9)               @ vAA<- r0
4461    GOTO_OPCODE(ip)                     @ jump to next instruction
4462    /* 11-14 instructions */
4463
4464
4465/* ------------------------------ */
4466    .balign 64
4467.L_OP_XOR_INT: /* 0x97 */
4468/* File: armv5te/OP_XOR_INT.S */
4469/* File: armv5te/binop.S */
4470    /*
4471     * Generic 32-bit binary operation.  Provide an "instr" line that
4472     * specifies an instruction that performs "result = r0 op r1".
4473     * This could be an ARM instruction or a function call.  (If the result
4474     * comes back in a register other than r0, you can override "result".)
4475     *
4476     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4477     * vCC (r1).  Useful for integer division and modulus.  Note that we
4478     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4479     * handles it correctly.
4480     *
4481     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4482     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4483     *      mul-float, div-float, rem-float
4484     */
4485    /* binop vAA, vBB, vCC */
4486    FETCH(r0, 1)                        @ r0<- CCBB
4487    mov     r9, rINST, lsr #8           @ r9<- AA
4488    mov     r3, r0, lsr #8              @ r3<- CC
4489    and     r2, r0, #255                @ r2<- BB
4490    GET_VREG(r1, r3)                    @ r1<- vCC
4491    GET_VREG(r0, r2)                    @ r0<- vBB
4492    .if 0
4493    cmp     r1, #0                      @ is second operand zero?
4494    beq     common_errDivideByZero
4495    .endif
4496
4497    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4498                               @ optional op; may set condition codes
4499    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
4500    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4501    SET_VREG(r0, r9)               @ vAA<- r0
4502    GOTO_OPCODE(ip)                     @ jump to next instruction
4503    /* 11-14 instructions */
4504
4505
4506/* ------------------------------ */
4507    .balign 64
4508.L_OP_SHL_INT: /* 0x98 */
4509/* File: armv5te/OP_SHL_INT.S */
4510/* File: armv5te/binop.S */
4511    /*
4512     * Generic 32-bit binary operation.  Provide an "instr" line that
4513     * specifies an instruction that performs "result = r0 op r1".
4514     * This could be an ARM instruction or a function call.  (If the result
4515     * comes back in a register other than r0, you can override "result".)
4516     *
4517     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4518     * vCC (r1).  Useful for integer division and modulus.  Note that we
4519     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4520     * handles it correctly.
4521     *
4522     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4523     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4524     *      mul-float, div-float, rem-float
4525     */
4526    /* binop vAA, vBB, vCC */
4527    FETCH(r0, 1)                        @ r0<- CCBB
4528    mov     r9, rINST, lsr #8           @ r9<- AA
4529    mov     r3, r0, lsr #8              @ r3<- CC
4530    and     r2, r0, #255                @ r2<- BB
4531    GET_VREG(r1, r3)                    @ r1<- vCC
4532    GET_VREG(r0, r2)                    @ r0<- vBB
4533    .if 0
4534    cmp     r1, #0                      @ is second operand zero?
4535    beq     common_errDivideByZero
4536    .endif
4537
4538    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4539    and     r1, r1, #31                           @ optional op; may set condition codes
4540    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
4541    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4542    SET_VREG(r0, r9)               @ vAA<- r0
4543    GOTO_OPCODE(ip)                     @ jump to next instruction
4544    /* 11-14 instructions */
4545
4546
4547/* ------------------------------ */
4548    .balign 64
4549.L_OP_SHR_INT: /* 0x99 */
4550/* File: armv5te/OP_SHR_INT.S */
4551/* File: armv5te/binop.S */
4552    /*
4553     * Generic 32-bit binary operation.  Provide an "instr" line that
4554     * specifies an instruction that performs "result = r0 op r1".
4555     * This could be an ARM instruction or a function call.  (If the result
4556     * comes back in a register other than r0, you can override "result".)
4557     *
4558     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4559     * vCC (r1).  Useful for integer division and modulus.  Note that we
4560     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4561     * handles it correctly.
4562     *
4563     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4564     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4565     *      mul-float, div-float, rem-float
4566     */
4567    /* binop vAA, vBB, vCC */
4568    FETCH(r0, 1)                        @ r0<- CCBB
4569    mov     r9, rINST, lsr #8           @ r9<- AA
4570    mov     r3, r0, lsr #8              @ r3<- CC
4571    and     r2, r0, #255                @ r2<- BB
4572    GET_VREG(r1, r3)                    @ r1<- vCC
4573    GET_VREG(r0, r2)                    @ r0<- vBB
4574    .if 0
4575    cmp     r1, #0                      @ is second operand zero?
4576    beq     common_errDivideByZero
4577    .endif
4578
4579    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4580    and     r1, r1, #31                           @ optional op; may set condition codes
4581    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
4582    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4583    SET_VREG(r0, r9)               @ vAA<- r0
4584    GOTO_OPCODE(ip)                     @ jump to next instruction
4585    /* 11-14 instructions */
4586
4587
4588/* ------------------------------ */
4589    .balign 64
4590.L_OP_USHR_INT: /* 0x9a */
4591/* File: armv5te/OP_USHR_INT.S */
4592/* File: armv5te/binop.S */
4593    /*
4594     * Generic 32-bit binary operation.  Provide an "instr" line that
4595     * specifies an instruction that performs "result = r0 op r1".
4596     * This could be an ARM instruction or a function call.  (If the result
4597     * comes back in a register other than r0, you can override "result".)
4598     *
4599     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4600     * vCC (r1).  Useful for integer division and modulus.  Note that we
4601     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
4602     * handles it correctly.
4603     *
4604     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
4605     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
4606     *      mul-float, div-float, rem-float
4607     */
4608    /* binop vAA, vBB, vCC */
4609    FETCH(r0, 1)                        @ r0<- CCBB
4610    mov     r9, rINST, lsr #8           @ r9<- AA
4611    mov     r3, r0, lsr #8              @ r3<- CC
4612    and     r2, r0, #255                @ r2<- BB
4613    GET_VREG(r1, r3)                    @ r1<- vCC
4614    GET_VREG(r0, r2)                    @ r0<- vBB
4615    .if 0
4616    cmp     r1, #0                      @ is second operand zero?
4617    beq     common_errDivideByZero
4618    .endif
4619
4620    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4621    and     r1, r1, #31                           @ optional op; may set condition codes
4622    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
4623    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4624    SET_VREG(r0, r9)               @ vAA<- r0
4625    GOTO_OPCODE(ip)                     @ jump to next instruction
4626    /* 11-14 instructions */
4627
4628
4629/* ------------------------------ */
4630    .balign 64
4631.L_OP_ADD_LONG: /* 0x9b */
4632/* File: armv5te/OP_ADD_LONG.S */
4633/* File: armv5te/binopWide.S */
4634    /*
4635     * Generic 64-bit binary operation.  Provide an "instr" line that
4636     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4637     * This could be an ARM instruction or a function call.  (If the result
4638     * comes back in a register other than r0, you can override "result".)
4639     *
4640     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4641     * vCC (r1).  Useful for integer division and modulus.
4642     *
4643     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4644     *      xor-long, add-double, sub-double, mul-double, div-double,
4645     *      rem-double
4646     *
4647     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4648     */
4649    /* binop vAA, vBB, vCC */
4650    FETCH(r0, 1)                        @ r0<- CCBB
4651    mov     r9, rINST, lsr #8           @ r9<- AA
4652    and     r2, r0, #255                @ r2<- BB
4653    mov     r3, r0, lsr #8              @ r3<- CC
4654    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4655    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4656    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4657    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4658    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4659    .if 0
4660    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4661    beq     common_errDivideByZero
4662    .endif
4663    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4664
4665    adds    r0, r0, r2                           @ optional op; may set condition codes
4666    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
4667    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4668    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4669    GOTO_OPCODE(ip)                     @ jump to next instruction
4670    /* 14-17 instructions */
4671
4672
4673/* ------------------------------ */
4674    .balign 64
4675.L_OP_SUB_LONG: /* 0x9c */
4676/* File: armv5te/OP_SUB_LONG.S */
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 0
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    subs    r0, r0, r2                           @ optional op; may set condition codes
4710    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
4711    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4712    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4713    GOTO_OPCODE(ip)                     @ jump to next instruction
4714    /* 14-17 instructions */
4715
4716
4717/* ------------------------------ */
4718    .balign 64
4719.L_OP_MUL_LONG: /* 0x9d */
4720/* File: armv5te/OP_MUL_LONG.S */
4721    /*
4722     * Signed 64-bit integer multiply.
4723     *
4724     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
4725     *        WX
4726     *      x YZ
4727     *  --------
4728     *     ZW ZX
4729     *  YW YX
4730     *
4731     * The low word of the result holds ZX, the high word holds
4732     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
4733     * it doesn't fit in the low 64 bits.
4734     *
4735     * Unlike most ARM math operations, multiply instructions have
4736     * restrictions on using the same register more than once (Rd and Rm
4737     * cannot be the same).
4738     */
4739    /* mul-long vAA, vBB, vCC */
4740    FETCH(r0, 1)                        @ r0<- CCBB
4741    and     r2, r0, #255                @ r2<- BB
4742    mov     r3, r0, lsr #8              @ r3<- CC
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    mul     ip, r2, r1                  @  ip<- ZxW
4748    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
4749    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
4750    mov     r0, rINST, lsr #8           @ r0<- AA
4751    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
4752    add     r0, rFP, r0, lsl #2         @ r0<- &fp[AA]
4753    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4754    b       .LOP_MUL_LONG_finish
4755
4756/* ------------------------------ */
4757    .balign 64
4758.L_OP_DIV_LONG: /* 0x9e */
4759/* File: armv5te/OP_DIV_LONG.S */
4760/* File: armv5te/binopWide.S */
4761    /*
4762     * Generic 64-bit binary operation.  Provide an "instr" line that
4763     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4764     * This could be an ARM instruction or a function call.  (If the result
4765     * comes back in a register other than r0, you can override "result".)
4766     *
4767     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4768     * vCC (r1).  Useful for integer division and modulus.
4769     *
4770     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4771     *      xor-long, add-double, sub-double, mul-double, div-double,
4772     *      rem-double
4773     *
4774     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4775     */
4776    /* binop vAA, vBB, vCC */
4777    FETCH(r0, 1)                        @ r0<- CCBB
4778    mov     r9, rINST, lsr #8           @ r9<- AA
4779    and     r2, r0, #255                @ r2<- BB
4780    mov     r3, r0, lsr #8              @ r3<- CC
4781    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4782    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4783    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4784    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4785    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4786    .if 1
4787    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4788    beq     common_errDivideByZero
4789    .endif
4790    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4791
4792                               @ optional op; may set condition codes
4793    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4794    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4795    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4796    GOTO_OPCODE(ip)                     @ jump to next instruction
4797    /* 14-17 instructions */
4798
4799
4800/* ------------------------------ */
4801    .balign 64
4802.L_OP_REM_LONG: /* 0x9f */
4803/* File: armv5te/OP_REM_LONG.S */
4804/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
4805/* File: armv5te/binopWide.S */
4806    /*
4807     * Generic 64-bit binary operation.  Provide an "instr" line that
4808     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4809     * This could be an ARM instruction or a function call.  (If the result
4810     * comes back in a register other than r0, you can override "result".)
4811     *
4812     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4813     * vCC (r1).  Useful for integer division and modulus.
4814     *
4815     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4816     *      xor-long, add-double, sub-double, mul-double, div-double,
4817     *      rem-double
4818     *
4819     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4820     */
4821    /* binop vAA, vBB, vCC */
4822    FETCH(r0, 1)                        @ r0<- CCBB
4823    mov     r9, rINST, lsr #8           @ r9<- AA
4824    and     r2, r0, #255                @ r2<- BB
4825    mov     r3, r0, lsr #8              @ r3<- CC
4826    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4827    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4828    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4829    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4830    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4831    .if 1
4832    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4833    beq     common_errDivideByZero
4834    .endif
4835    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4836
4837                               @ optional op; may set condition codes
4838    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
4839    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4840    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
4841    GOTO_OPCODE(ip)                     @ jump to next instruction
4842    /* 14-17 instructions */
4843
4844
4845/* ------------------------------ */
4846    .balign 64
4847.L_OP_AND_LONG: /* 0xa0 */
4848/* File: armv5te/OP_AND_LONG.S */
4849/* File: armv5te/binopWide.S */
4850    /*
4851     * Generic 64-bit binary operation.  Provide an "instr" line that
4852     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4853     * This could be an ARM instruction or a function call.  (If the result
4854     * comes back in a register other than r0, you can override "result".)
4855     *
4856     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4857     * vCC (r1).  Useful for integer division and modulus.
4858     *
4859     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4860     *      xor-long, add-double, sub-double, mul-double, div-double,
4861     *      rem-double
4862     *
4863     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4864     */
4865    /* binop vAA, vBB, vCC */
4866    FETCH(r0, 1)                        @ r0<- CCBB
4867    mov     r9, rINST, lsr #8           @ r9<- AA
4868    and     r2, r0, #255                @ r2<- BB
4869    mov     r3, r0, lsr #8              @ r3<- CC
4870    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4871    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4872    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4873    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4874    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4875    .if 0
4876    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4877    beq     common_errDivideByZero
4878    .endif
4879    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4880
4881    and     r0, r0, r2                           @ optional op; may set condition codes
4882    and     r1, r1, r3                              @ result<- op, r0-r3 changed
4883    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4884    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4885    GOTO_OPCODE(ip)                     @ jump to next instruction
4886    /* 14-17 instructions */
4887
4888
4889/* ------------------------------ */
4890    .balign 64
4891.L_OP_OR_LONG: /* 0xa1 */
4892/* File: armv5te/OP_OR_LONG.S */
4893/* File: armv5te/binopWide.S */
4894    /*
4895     * Generic 64-bit binary operation.  Provide an "instr" line that
4896     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4897     * This could be an ARM instruction or a function call.  (If the result
4898     * comes back in a register other than r0, you can override "result".)
4899     *
4900     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4901     * vCC (r1).  Useful for integer division and modulus.
4902     *
4903     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4904     *      xor-long, add-double, sub-double, mul-double, div-double,
4905     *      rem-double
4906     *
4907     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4908     */
4909    /* binop vAA, vBB, vCC */
4910    FETCH(r0, 1)                        @ r0<- CCBB
4911    mov     r9, rINST, lsr #8           @ r9<- AA
4912    and     r2, r0, #255                @ r2<- BB
4913    mov     r3, r0, lsr #8              @ r3<- CC
4914    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4915    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4916    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4917    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4918    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4919    .if 0
4920    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4921    beq     common_errDivideByZero
4922    .endif
4923    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4924
4925    orr     r0, r0, r2                           @ optional op; may set condition codes
4926    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
4927    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4928    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4929    GOTO_OPCODE(ip)                     @ jump to next instruction
4930    /* 14-17 instructions */
4931
4932
4933/* ------------------------------ */
4934    .balign 64
4935.L_OP_XOR_LONG: /* 0xa2 */
4936/* File: armv5te/OP_XOR_LONG.S */
4937/* File: armv5te/binopWide.S */
4938    /*
4939     * Generic 64-bit binary operation.  Provide an "instr" line that
4940     * specifies an instruction that performs "result = r0-r1 op r2-r3".
4941     * This could be an ARM instruction or a function call.  (If the result
4942     * comes back in a register other than r0, you can override "result".)
4943     *
4944     * If "chkzero" is set to 1, we perform a divide-by-zero check on
4945     * vCC (r1).  Useful for integer division and modulus.
4946     *
4947     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
4948     *      xor-long, add-double, sub-double, mul-double, div-double,
4949     *      rem-double
4950     *
4951     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
4952     */
4953    /* binop vAA, vBB, vCC */
4954    FETCH(r0, 1)                        @ r0<- CCBB
4955    mov     r9, rINST, lsr #8           @ r9<- AA
4956    and     r2, r0, #255                @ r2<- BB
4957    mov     r3, r0, lsr #8              @ r3<- CC
4958    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4959    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
4960    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
4961    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4962    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
4963    .if 0
4964    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
4965    beq     common_errDivideByZero
4966    .endif
4967    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
4968
4969    eor     r0, r0, r2                           @ optional op; may set condition codes
4970    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
4971    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
4972    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
4973    GOTO_OPCODE(ip)                     @ jump to next instruction
4974    /* 14-17 instructions */
4975
4976
4977/* ------------------------------ */
4978    .balign 64
4979.L_OP_SHL_LONG: /* 0xa3 */
4980/* File: armv5te/OP_SHL_LONG.S */
4981    /*
4982     * Long integer shift.  This is different from the generic 32/64-bit
4983     * binary operations because vAA/vBB are 64-bit but vCC (the shift
4984     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
4985     * 6 bits of the shift distance.
4986     */
4987    /* shl-long vAA, vBB, vCC */
4988    FETCH(r0, 1)                        @ r0<- CCBB
4989    mov     r9, rINST, lsr #8           @ r9<- AA
4990    and     r3, r0, #255                @ r3<- BB
4991    mov     r0, r0, lsr #8              @ r0<- CC
4992    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
4993    GET_VREG(r2, r0)                    @ r2<- vCC
4994    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
4995    and     r2, r2, #63                 @ r2<- r2 & 0x3f
4996    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
4997
4998    mov     r1, r1, asl r2              @  r1<- r1 << r2
4999    rsb     r3, r2, #32                 @  r3<- 32 - r2
5000    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
5001    subs    ip, r2, #32                 @  ip<- r2 - 32
5002    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
5003    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5004    b       .LOP_SHL_LONG_finish
5005
5006/* ------------------------------ */
5007    .balign 64
5008.L_OP_SHR_LONG: /* 0xa4 */
5009/* File: armv5te/OP_SHR_LONG.S */
5010    /*
5011     * Long integer shift.  This is different from the generic 32/64-bit
5012     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5013     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5014     * 6 bits of the shift distance.
5015     */
5016    /* shr-long vAA, vBB, vCC */
5017    FETCH(r0, 1)                        @ r0<- CCBB
5018    mov     r9, rINST, lsr #8           @ r9<- AA
5019    and     r3, r0, #255                @ r3<- BB
5020    mov     r0, r0, lsr #8              @ r0<- CC
5021    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5022    GET_VREG(r2, r0)                    @ r2<- vCC
5023    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5024    and     r2, r2, #63                 @ r0<- r0 & 0x3f
5025    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5026
5027    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5028    rsb     r3, r2, #32                 @  r3<- 32 - r2
5029    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5030    subs    ip, r2, #32                 @  ip<- r2 - 32
5031    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
5032    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5033    b       .LOP_SHR_LONG_finish
5034
5035/* ------------------------------ */
5036    .balign 64
5037.L_OP_USHR_LONG: /* 0xa5 */
5038/* File: armv5te/OP_USHR_LONG.S */
5039    /*
5040     * Long integer shift.  This is different from the generic 32/64-bit
5041     * binary operations because vAA/vBB are 64-bit but vCC (the shift
5042     * distance) is 32-bit.  Also, Dalvik requires us to mask off the low
5043     * 6 bits of the shift distance.
5044     */
5045    /* ushr-long vAA, vBB, vCC */
5046    FETCH(r0, 1)                        @ r0<- CCBB
5047    mov     r9, rINST, lsr #8           @ r9<- AA
5048    and     r3, r0, #255                @ r3<- BB
5049    mov     r0, r0, lsr #8              @ r0<- CC
5050    add     r3, rFP, r3, lsl #2         @ r3<- &fp[BB]
5051    GET_VREG(r2, r0)                    @ r2<- vCC
5052    ldmia   r3, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5053    and     r2, r2, #63                 @ r0<- r0 & 0x3f
5054    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5055
5056    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
5057    rsb     r3, r2, #32                 @  r3<- 32 - r2
5058    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
5059    subs    ip, r2, #32                 @  ip<- r2 - 32
5060    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
5061    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5062    b       .LOP_USHR_LONG_finish
5063
5064/* ------------------------------ */
5065    .balign 64
5066.L_OP_ADD_FLOAT: /* 0xa6 */
5067/* File: armv5te/OP_ADD_FLOAT.S */
5068/* File: armv5te/binop.S */
5069    /*
5070     * Generic 32-bit binary operation.  Provide an "instr" line that
5071     * specifies an instruction that performs "result = r0 op r1".
5072     * This could be an ARM instruction or a function call.  (If the result
5073     * comes back in a register other than r0, you can override "result".)
5074     *
5075     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5076     * vCC (r1).  Useful for integer division and modulus.  Note that we
5077     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5078     * handles it correctly.
5079     *
5080     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5081     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5082     *      mul-float, div-float, rem-float
5083     */
5084    /* binop vAA, vBB, vCC */
5085    FETCH(r0, 1)                        @ r0<- CCBB
5086    mov     r9, rINST, lsr #8           @ r9<- AA
5087    mov     r3, r0, lsr #8              @ r3<- CC
5088    and     r2, r0, #255                @ r2<- BB
5089    GET_VREG(r1, r3)                    @ r1<- vCC
5090    GET_VREG(r0, r2)                    @ r0<- vBB
5091    .if 0
5092    cmp     r1, #0                      @ is second operand zero?
5093    beq     common_errDivideByZero
5094    .endif
5095
5096    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5097                               @ optional op; may set condition codes
5098    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
5099    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5100    SET_VREG(r0, r9)               @ vAA<- r0
5101    GOTO_OPCODE(ip)                     @ jump to next instruction
5102    /* 11-14 instructions */
5103
5104
5105/* ------------------------------ */
5106    .balign 64
5107.L_OP_SUB_FLOAT: /* 0xa7 */
5108/* File: armv5te/OP_SUB_FLOAT.S */
5109/* File: armv5te/binop.S */
5110    /*
5111     * Generic 32-bit binary operation.  Provide an "instr" line that
5112     * specifies an instruction that performs "result = r0 op r1".
5113     * This could be an ARM instruction or a function call.  (If the result
5114     * comes back in a register other than r0, you can override "result".)
5115     *
5116     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5117     * vCC (r1).  Useful for integer division and modulus.  Note that we
5118     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5119     * handles it correctly.
5120     *
5121     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5122     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5123     *      mul-float, div-float, rem-float
5124     */
5125    /* binop vAA, vBB, vCC */
5126    FETCH(r0, 1)                        @ r0<- CCBB
5127    mov     r9, rINST, lsr #8           @ r9<- AA
5128    mov     r3, r0, lsr #8              @ r3<- CC
5129    and     r2, r0, #255                @ r2<- BB
5130    GET_VREG(r1, r3)                    @ r1<- vCC
5131    GET_VREG(r0, r2)                    @ r0<- vBB
5132    .if 0
5133    cmp     r1, #0                      @ is second operand zero?
5134    beq     common_errDivideByZero
5135    .endif
5136
5137    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5138                               @ optional op; may set condition codes
5139    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
5140    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5141    SET_VREG(r0, r9)               @ vAA<- r0
5142    GOTO_OPCODE(ip)                     @ jump to next instruction
5143    /* 11-14 instructions */
5144
5145
5146/* ------------------------------ */
5147    .balign 64
5148.L_OP_MUL_FLOAT: /* 0xa8 */
5149/* File: armv5te/OP_MUL_FLOAT.S */
5150/* File: armv5te/binop.S */
5151    /*
5152     * Generic 32-bit binary operation.  Provide an "instr" line that
5153     * specifies an instruction that performs "result = r0 op r1".
5154     * This could be an ARM instruction or a function call.  (If the result
5155     * comes back in a register other than r0, you can override "result".)
5156     *
5157     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5158     * vCC (r1).  Useful for integer division and modulus.  Note that we
5159     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5160     * handles it correctly.
5161     *
5162     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5163     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5164     *      mul-float, div-float, rem-float
5165     */
5166    /* binop vAA, vBB, vCC */
5167    FETCH(r0, 1)                        @ r0<- CCBB
5168    mov     r9, rINST, lsr #8           @ r9<- AA
5169    mov     r3, r0, lsr #8              @ r3<- CC
5170    and     r2, r0, #255                @ r2<- BB
5171    GET_VREG(r1, r3)                    @ r1<- vCC
5172    GET_VREG(r0, r2)                    @ r0<- vBB
5173    .if 0
5174    cmp     r1, #0                      @ is second operand zero?
5175    beq     common_errDivideByZero
5176    .endif
5177
5178    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5179                               @ optional op; may set condition codes
5180    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
5181    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5182    SET_VREG(r0, r9)               @ vAA<- r0
5183    GOTO_OPCODE(ip)                     @ jump to next instruction
5184    /* 11-14 instructions */
5185
5186
5187/* ------------------------------ */
5188    .balign 64
5189.L_OP_DIV_FLOAT: /* 0xa9 */
5190/* File: armv5te/OP_DIV_FLOAT.S */
5191/* File: armv5te/binop.S */
5192    /*
5193     * Generic 32-bit binary operation.  Provide an "instr" line that
5194     * specifies an instruction that performs "result = r0 op r1".
5195     * This could be an ARM instruction or a function call.  (If the result
5196     * comes back in a register other than r0, you can override "result".)
5197     *
5198     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5199     * vCC (r1).  Useful for integer division and modulus.  Note that we
5200     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5201     * handles it correctly.
5202     *
5203     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5204     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5205     *      mul-float, div-float, rem-float
5206     */
5207    /* binop vAA, vBB, vCC */
5208    FETCH(r0, 1)                        @ r0<- CCBB
5209    mov     r9, rINST, lsr #8           @ r9<- AA
5210    mov     r3, r0, lsr #8              @ r3<- CC
5211    and     r2, r0, #255                @ r2<- BB
5212    GET_VREG(r1, r3)                    @ r1<- vCC
5213    GET_VREG(r0, r2)                    @ r0<- vBB
5214    .if 0
5215    cmp     r1, #0                      @ is second operand zero?
5216    beq     common_errDivideByZero
5217    .endif
5218
5219    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5220                               @ optional op; may set condition codes
5221    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
5222    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5223    SET_VREG(r0, r9)               @ vAA<- r0
5224    GOTO_OPCODE(ip)                     @ jump to next instruction
5225    /* 11-14 instructions */
5226
5227
5228/* ------------------------------ */
5229    .balign 64
5230.L_OP_REM_FLOAT: /* 0xaa */
5231/* File: armv5te/OP_REM_FLOAT.S */
5232/* EABI doesn't define a float remainder function, but libm does */
5233/* File: armv5te/binop.S */
5234    /*
5235     * Generic 32-bit binary operation.  Provide an "instr" line that
5236     * specifies an instruction that performs "result = r0 op r1".
5237     * This could be an ARM instruction or a function call.  (If the result
5238     * comes back in a register other than r0, you can override "result".)
5239     *
5240     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5241     * vCC (r1).  Useful for integer division and modulus.  Note that we
5242     * *don't* check for (INT_MIN / -1) here, because the ARM math lib
5243     * handles it correctly.
5244     *
5245     * For: add-int, sub-int, mul-int, div-int, rem-int, and-int, or-int,
5246     *      xor-int, shl-int, shr-int, ushr-int, add-float, sub-float,
5247     *      mul-float, div-float, rem-float
5248     */
5249    /* binop vAA, vBB, vCC */
5250    FETCH(r0, 1)                        @ r0<- CCBB
5251    mov     r9, rINST, lsr #8           @ r9<- AA
5252    mov     r3, r0, lsr #8              @ r3<- CC
5253    and     r2, r0, #255                @ r2<- BB
5254    GET_VREG(r1, r3)                    @ r1<- vCC
5255    GET_VREG(r0, r2)                    @ r0<- vBB
5256    .if 0
5257    cmp     r1, #0                      @ is second operand zero?
5258    beq     common_errDivideByZero
5259    .endif
5260
5261    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5262                               @ optional op; may set condition codes
5263    bl      fmodf                              @ r0<- op, r0-r3 changed
5264    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5265    SET_VREG(r0, r9)               @ vAA<- r0
5266    GOTO_OPCODE(ip)                     @ jump to next instruction
5267    /* 11-14 instructions */
5268
5269
5270/* ------------------------------ */
5271    .balign 64
5272.L_OP_ADD_DOUBLE: /* 0xab */
5273/* File: armv5te/OP_ADD_DOUBLE.S */
5274/* File: armv5te/binopWide.S */
5275    /*
5276     * Generic 64-bit binary operation.  Provide an "instr" line that
5277     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5278     * This could be an ARM instruction or a function call.  (If the result
5279     * comes back in a register other than r0, you can override "result".)
5280     *
5281     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5282     * vCC (r1).  Useful for integer division and modulus.
5283     *
5284     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5285     *      xor-long, add-double, sub-double, mul-double, div-double,
5286     *      rem-double
5287     *
5288     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5289     */
5290    /* binop vAA, vBB, vCC */
5291    FETCH(r0, 1)                        @ r0<- CCBB
5292    mov     r9, rINST, lsr #8           @ r9<- AA
5293    and     r2, r0, #255                @ r2<- BB
5294    mov     r3, r0, lsr #8              @ r3<- CC
5295    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5296    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5297    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5298    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5299    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5300    .if 0
5301    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5302    beq     common_errDivideByZero
5303    .endif
5304    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5305
5306                               @ optional op; may set condition codes
5307    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
5308    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5309    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5310    GOTO_OPCODE(ip)                     @ jump to next instruction
5311    /* 14-17 instructions */
5312
5313
5314/* ------------------------------ */
5315    .balign 64
5316.L_OP_SUB_DOUBLE: /* 0xac */
5317/* File: armv5te/OP_SUB_DOUBLE.S */
5318/* File: armv5te/binopWide.S */
5319    /*
5320     * Generic 64-bit binary operation.  Provide an "instr" line that
5321     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5322     * This could be an ARM instruction or a function call.  (If the result
5323     * comes back in a register other than r0, you can override "result".)
5324     *
5325     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5326     * vCC (r1).  Useful for integer division and modulus.
5327     *
5328     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5329     *      xor-long, add-double, sub-double, mul-double, div-double,
5330     *      rem-double
5331     *
5332     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5333     */
5334    /* binop vAA, vBB, vCC */
5335    FETCH(r0, 1)                        @ r0<- CCBB
5336    mov     r9, rINST, lsr #8           @ r9<- AA
5337    and     r2, r0, #255                @ r2<- BB
5338    mov     r3, r0, lsr #8              @ r3<- CC
5339    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5340    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5341    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5342    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5343    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5344    .if 0
5345    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5346    beq     common_errDivideByZero
5347    .endif
5348    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5349
5350                               @ optional op; may set condition codes
5351    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
5352    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5353    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5354    GOTO_OPCODE(ip)                     @ jump to next instruction
5355    /* 14-17 instructions */
5356
5357
5358/* ------------------------------ */
5359    .balign 64
5360.L_OP_MUL_DOUBLE: /* 0xad */
5361/* File: armv5te/OP_MUL_DOUBLE.S */
5362/* File: armv5te/binopWide.S */
5363    /*
5364     * Generic 64-bit binary operation.  Provide an "instr" line that
5365     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5366     * This could be an ARM instruction or a function call.  (If the result
5367     * comes back in a register other than r0, you can override "result".)
5368     *
5369     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5370     * vCC (r1).  Useful for integer division and modulus.
5371     *
5372     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5373     *      xor-long, add-double, sub-double, mul-double, div-double,
5374     *      rem-double
5375     *
5376     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5377     */
5378    /* binop vAA, vBB, vCC */
5379    FETCH(r0, 1)                        @ r0<- CCBB
5380    mov     r9, rINST, lsr #8           @ r9<- AA
5381    and     r2, r0, #255                @ r2<- BB
5382    mov     r3, r0, lsr #8              @ r3<- CC
5383    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5384    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5385    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5386    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5387    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5388    .if 0
5389    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5390    beq     common_errDivideByZero
5391    .endif
5392    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5393
5394                               @ optional op; may set condition codes
5395    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
5396    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5397    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5398    GOTO_OPCODE(ip)                     @ jump to next instruction
5399    /* 14-17 instructions */
5400
5401
5402/* ------------------------------ */
5403    .balign 64
5404.L_OP_DIV_DOUBLE: /* 0xae */
5405/* File: armv5te/OP_DIV_DOUBLE.S */
5406/* File: armv5te/binopWide.S */
5407    /*
5408     * Generic 64-bit binary operation.  Provide an "instr" line that
5409     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5410     * This could be an ARM instruction or a function call.  (If the result
5411     * comes back in a register other than r0, you can override "result".)
5412     *
5413     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5414     * vCC (r1).  Useful for integer division and modulus.
5415     *
5416     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5417     *      xor-long, add-double, sub-double, mul-double, div-double,
5418     *      rem-double
5419     *
5420     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5421     */
5422    /* binop vAA, vBB, vCC */
5423    FETCH(r0, 1)                        @ r0<- CCBB
5424    mov     r9, rINST, lsr #8           @ r9<- AA
5425    and     r2, r0, #255                @ r2<- BB
5426    mov     r3, r0, lsr #8              @ r3<- CC
5427    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5428    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5429    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5430    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5431    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5432    .if 0
5433    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5434    beq     common_errDivideByZero
5435    .endif
5436    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5437
5438                               @ optional op; may set condition codes
5439    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
5440    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5441    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5442    GOTO_OPCODE(ip)                     @ jump to next instruction
5443    /* 14-17 instructions */
5444
5445
5446/* ------------------------------ */
5447    .balign 64
5448.L_OP_REM_DOUBLE: /* 0xaf */
5449/* File: armv5te/OP_REM_DOUBLE.S */
5450/* EABI doesn't define a double remainder function, but libm does */
5451/* File: armv5te/binopWide.S */
5452    /*
5453     * Generic 64-bit binary operation.  Provide an "instr" line that
5454     * specifies an instruction that performs "result = r0-r1 op r2-r3".
5455     * This could be an ARM instruction or a function call.  (If the result
5456     * comes back in a register other than r0, you can override "result".)
5457     *
5458     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5459     * vCC (r1).  Useful for integer division and modulus.
5460     *
5461     * for: add-long, sub-long, div-long, rem-long, and-long, or-long,
5462     *      xor-long, add-double, sub-double, mul-double, div-double,
5463     *      rem-double
5464     *
5465     * IMPORTANT: you may specify "chkzero" or "preinstr" but not both.
5466     */
5467    /* binop vAA, vBB, vCC */
5468    FETCH(r0, 1)                        @ r0<- CCBB
5469    mov     r9, rINST, lsr #8           @ r9<- AA
5470    and     r2, r0, #255                @ r2<- BB
5471    mov     r3, r0, lsr #8              @ r3<- CC
5472    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
5473    add     r2, rFP, r2, lsl #2         @ r2<- &fp[BB]
5474    add     r3, rFP, r3, lsl #2         @ r3<- &fp[CC]
5475    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
5476    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
5477    .if 0
5478    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5479    beq     common_errDivideByZero
5480    .endif
5481    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
5482
5483                               @ optional op; may set condition codes
5484    bl      fmod                              @ result<- op, r0-r3 changed
5485    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5486    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5487    GOTO_OPCODE(ip)                     @ jump to next instruction
5488    /* 14-17 instructions */
5489
5490
5491/* ------------------------------ */
5492    .balign 64
5493.L_OP_ADD_INT_2ADDR: /* 0xb0 */
5494/* File: armv5te/OP_ADD_INT_2ADDR.S */
5495/* File: armv5te/binop2addr.S */
5496    /*
5497     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5498     * that specifies an instruction that performs "result = r0 op r1".
5499     * This could be an ARM instruction or a function call.  (If the result
5500     * comes back in a register other than r0, you can override "result".)
5501     *
5502     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5503     * vCC (r1).  Useful for integer division and modulus.
5504     *
5505     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5506     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5507     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5508     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5509     */
5510    /* binop/2addr vA, vB */
5511    mov     r9, rINST, lsr #8           @ r9<- A+
5512    mov     r3, rINST, lsr #12          @ r3<- B
5513    and     r9, r9, #15
5514    GET_VREG(r1, r3)                    @ r1<- vB
5515    GET_VREG(r0, r9)                    @ r0<- vA
5516    .if 0
5517    cmp     r1, #0                      @ is second operand zero?
5518    beq     common_errDivideByZero
5519    .endif
5520    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5521
5522                               @ optional op; may set condition codes
5523    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
5524    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5525    SET_VREG(r0, r9)               @ vAA<- r0
5526    GOTO_OPCODE(ip)                     @ jump to next instruction
5527    /* 10-13 instructions */
5528
5529
5530/* ------------------------------ */
5531    .balign 64
5532.L_OP_SUB_INT_2ADDR: /* 0xb1 */
5533/* File: armv5te/OP_SUB_INT_2ADDR.S */
5534/* File: armv5te/binop2addr.S */
5535    /*
5536     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5537     * that specifies an instruction that performs "result = r0 op r1".
5538     * This could be an ARM instruction or a function call.  (If the result
5539     * comes back in a register other than r0, you can override "result".)
5540     *
5541     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5542     * vCC (r1).  Useful for integer division and modulus.
5543     *
5544     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5545     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5546     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5547     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5548     */
5549    /* binop/2addr vA, vB */
5550    mov     r9, rINST, lsr #8           @ r9<- A+
5551    mov     r3, rINST, lsr #12          @ r3<- B
5552    and     r9, r9, #15
5553    GET_VREG(r1, r3)                    @ r1<- vB
5554    GET_VREG(r0, r9)                    @ r0<- vA
5555    .if 0
5556    cmp     r1, #0                      @ is second operand zero?
5557    beq     common_errDivideByZero
5558    .endif
5559    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5560
5561                               @ optional op; may set condition codes
5562    sub     r0, r0, r1                              @ r0<- op, r0-r3 changed
5563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5564    SET_VREG(r0, r9)               @ vAA<- r0
5565    GOTO_OPCODE(ip)                     @ jump to next instruction
5566    /* 10-13 instructions */
5567
5568
5569/* ------------------------------ */
5570    .balign 64
5571.L_OP_MUL_INT_2ADDR: /* 0xb2 */
5572/* File: armv5te/OP_MUL_INT_2ADDR.S */
5573/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
5574/* File: armv5te/binop2addr.S */
5575    /*
5576     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5577     * that specifies an instruction that performs "result = r0 op r1".
5578     * This could be an ARM instruction or a function call.  (If the result
5579     * comes back in a register other than r0, you can override "result".)
5580     *
5581     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5582     * vCC (r1).  Useful for integer division and modulus.
5583     *
5584     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5585     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5586     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5587     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5588     */
5589    /* binop/2addr vA, vB */
5590    mov     r9, rINST, lsr #8           @ r9<- A+
5591    mov     r3, rINST, lsr #12          @ r3<- B
5592    and     r9, r9, #15
5593    GET_VREG(r1, r3)                    @ r1<- vB
5594    GET_VREG(r0, r9)                    @ r0<- vA
5595    .if 0
5596    cmp     r1, #0                      @ is second operand zero?
5597    beq     common_errDivideByZero
5598    .endif
5599    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5600
5601                               @ optional op; may set condition codes
5602    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
5603    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5604    SET_VREG(r0, r9)               @ vAA<- r0
5605    GOTO_OPCODE(ip)                     @ jump to next instruction
5606    /* 10-13 instructions */
5607
5608
5609/* ------------------------------ */
5610    .balign 64
5611.L_OP_DIV_INT_2ADDR: /* 0xb3 */
5612/* File: armv5te/OP_DIV_INT_2ADDR.S */
5613/* File: armv5te/binop2addr.S */
5614    /*
5615     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5616     * that specifies an instruction that performs "result = r0 op r1".
5617     * This could be an ARM instruction or a function call.  (If the result
5618     * comes back in a register other than r0, you can override "result".)
5619     *
5620     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5621     * vCC (r1).  Useful for integer division and modulus.
5622     *
5623     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5624     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5625     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5626     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5627     */
5628    /* binop/2addr vA, vB */
5629    mov     r9, rINST, lsr #8           @ r9<- A+
5630    mov     r3, rINST, lsr #12          @ r3<- B
5631    and     r9, r9, #15
5632    GET_VREG(r1, r3)                    @ r1<- vB
5633    GET_VREG(r0, r9)                    @ r0<- vA
5634    .if 1
5635    cmp     r1, #0                      @ is second operand zero?
5636    beq     common_errDivideByZero
5637    .endif
5638    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5639
5640                               @ optional op; may set condition codes
5641    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
5642    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5643    SET_VREG(r0, r9)               @ vAA<- r0
5644    GOTO_OPCODE(ip)                     @ jump to next instruction
5645    /* 10-13 instructions */
5646
5647
5648/* ------------------------------ */
5649    .balign 64
5650.L_OP_REM_INT_2ADDR: /* 0xb4 */
5651/* File: armv5te/OP_REM_INT_2ADDR.S */
5652/* idivmod returns quotient in r0 and remainder in r1 */
5653/* File: armv5te/binop2addr.S */
5654    /*
5655     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5656     * that specifies an instruction that performs "result = r0 op r1".
5657     * This could be an ARM instruction or a function call.  (If the result
5658     * comes back in a register other than r0, you can override "result".)
5659     *
5660     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5661     * vCC (r1).  Useful for integer division and modulus.
5662     *
5663     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5664     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5665     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5666     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5667     */
5668    /* binop/2addr vA, vB */
5669    mov     r9, rINST, lsr #8           @ r9<- A+
5670    mov     r3, rINST, lsr #12          @ r3<- B
5671    and     r9, r9, #15
5672    GET_VREG(r1, r3)                    @ r1<- vB
5673    GET_VREG(r0, r9)                    @ r0<- vA
5674    .if 1
5675    cmp     r1, #0                      @ is second operand zero?
5676    beq     common_errDivideByZero
5677    .endif
5678    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5679
5680                               @ optional op; may set condition codes
5681    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
5682    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5683    SET_VREG(r1, r9)               @ vAA<- r1
5684    GOTO_OPCODE(ip)                     @ jump to next instruction
5685    /* 10-13 instructions */
5686
5687
5688/* ------------------------------ */
5689    .balign 64
5690.L_OP_AND_INT_2ADDR: /* 0xb5 */
5691/* File: armv5te/OP_AND_INT_2ADDR.S */
5692/* File: armv5te/binop2addr.S */
5693    /*
5694     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5695     * that specifies an instruction that performs "result = r0 op r1".
5696     * This could be an ARM instruction or a function call.  (If the result
5697     * comes back in a register other than r0, you can override "result".)
5698     *
5699     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5700     * vCC (r1).  Useful for integer division and modulus.
5701     *
5702     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5703     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5704     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5705     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5706     */
5707    /* binop/2addr vA, vB */
5708    mov     r9, rINST, lsr #8           @ r9<- A+
5709    mov     r3, rINST, lsr #12          @ r3<- B
5710    and     r9, r9, #15
5711    GET_VREG(r1, r3)                    @ r1<- vB
5712    GET_VREG(r0, r9)                    @ r0<- vA
5713    .if 0
5714    cmp     r1, #0                      @ is second operand zero?
5715    beq     common_errDivideByZero
5716    .endif
5717    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5718
5719                               @ optional op; may set condition codes
5720    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
5721    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5722    SET_VREG(r0, r9)               @ vAA<- r0
5723    GOTO_OPCODE(ip)                     @ jump to next instruction
5724    /* 10-13 instructions */
5725
5726
5727/* ------------------------------ */
5728    .balign 64
5729.L_OP_OR_INT_2ADDR: /* 0xb6 */
5730/* File: armv5te/OP_OR_INT_2ADDR.S */
5731/* File: armv5te/binop2addr.S */
5732    /*
5733     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5734     * that specifies an instruction that performs "result = r0 op r1".
5735     * This could be an ARM instruction or a function call.  (If the result
5736     * comes back in a register other than r0, you can override "result".)
5737     *
5738     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5739     * vCC (r1).  Useful for integer division and modulus.
5740     *
5741     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5742     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5743     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5744     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5745     */
5746    /* binop/2addr vA, vB */
5747    mov     r9, rINST, lsr #8           @ r9<- A+
5748    mov     r3, rINST, lsr #12          @ r3<- B
5749    and     r9, r9, #15
5750    GET_VREG(r1, r3)                    @ r1<- vB
5751    GET_VREG(r0, r9)                    @ r0<- vA
5752    .if 0
5753    cmp     r1, #0                      @ is second operand zero?
5754    beq     common_errDivideByZero
5755    .endif
5756    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5757
5758                               @ optional op; may set condition codes
5759    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
5760    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5761    SET_VREG(r0, r9)               @ vAA<- r0
5762    GOTO_OPCODE(ip)                     @ jump to next instruction
5763    /* 10-13 instructions */
5764
5765
5766/* ------------------------------ */
5767    .balign 64
5768.L_OP_XOR_INT_2ADDR: /* 0xb7 */
5769/* File: armv5te/OP_XOR_INT_2ADDR.S */
5770/* File: armv5te/binop2addr.S */
5771    /*
5772     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5773     * that specifies an instruction that performs "result = r0 op r1".
5774     * This could be an ARM instruction or a function call.  (If the result
5775     * comes back in a register other than r0, you can override "result".)
5776     *
5777     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5778     * vCC (r1).  Useful for integer division and modulus.
5779     *
5780     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5781     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5782     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5783     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5784     */
5785    /* binop/2addr vA, vB */
5786    mov     r9, rINST, lsr #8           @ r9<- A+
5787    mov     r3, rINST, lsr #12          @ r3<- B
5788    and     r9, r9, #15
5789    GET_VREG(r1, r3)                    @ r1<- vB
5790    GET_VREG(r0, r9)                    @ r0<- vA
5791    .if 0
5792    cmp     r1, #0                      @ is second operand zero?
5793    beq     common_errDivideByZero
5794    .endif
5795    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5796
5797                               @ optional op; may set condition codes
5798    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
5799    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5800    SET_VREG(r0, r9)               @ vAA<- r0
5801    GOTO_OPCODE(ip)                     @ jump to next instruction
5802    /* 10-13 instructions */
5803
5804
5805/* ------------------------------ */
5806    .balign 64
5807.L_OP_SHL_INT_2ADDR: /* 0xb8 */
5808/* File: armv5te/OP_SHL_INT_2ADDR.S */
5809/* File: armv5te/binop2addr.S */
5810    /*
5811     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5812     * that specifies an instruction that performs "result = r0 op r1".
5813     * This could be an ARM instruction or a function call.  (If the result
5814     * comes back in a register other than r0, you can override "result".)
5815     *
5816     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5817     * vCC (r1).  Useful for integer division and modulus.
5818     *
5819     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5820     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5821     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5822     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5823     */
5824    /* binop/2addr vA, vB */
5825    mov     r9, rINST, lsr #8           @ r9<- A+
5826    mov     r3, rINST, lsr #12          @ r3<- B
5827    and     r9, r9, #15
5828    GET_VREG(r1, r3)                    @ r1<- vB
5829    GET_VREG(r0, r9)                    @ r0<- vA
5830    .if 0
5831    cmp     r1, #0                      @ is second operand zero?
5832    beq     common_errDivideByZero
5833    .endif
5834    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5835
5836    and     r1, r1, #31                           @ optional op; may set condition codes
5837    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
5838    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5839    SET_VREG(r0, r9)               @ vAA<- r0
5840    GOTO_OPCODE(ip)                     @ jump to next instruction
5841    /* 10-13 instructions */
5842
5843
5844/* ------------------------------ */
5845    .balign 64
5846.L_OP_SHR_INT_2ADDR: /* 0xb9 */
5847/* File: armv5te/OP_SHR_INT_2ADDR.S */
5848/* File: armv5te/binop2addr.S */
5849    /*
5850     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5851     * that specifies an instruction that performs "result = r0 op r1".
5852     * This could be an ARM instruction or a function call.  (If the result
5853     * comes back in a register other than r0, you can override "result".)
5854     *
5855     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5856     * vCC (r1).  Useful for integer division and modulus.
5857     *
5858     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5859     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5860     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5861     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5862     */
5863    /* binop/2addr vA, vB */
5864    mov     r9, rINST, lsr #8           @ r9<- A+
5865    mov     r3, rINST, lsr #12          @ r3<- B
5866    and     r9, r9, #15
5867    GET_VREG(r1, r3)                    @ r1<- vB
5868    GET_VREG(r0, r9)                    @ r0<- vA
5869    .if 0
5870    cmp     r1, #0                      @ is second operand zero?
5871    beq     common_errDivideByZero
5872    .endif
5873    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5874
5875    and     r1, r1, #31                           @ optional op; may set condition codes
5876    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
5877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5878    SET_VREG(r0, r9)               @ vAA<- r0
5879    GOTO_OPCODE(ip)                     @ jump to next instruction
5880    /* 10-13 instructions */
5881
5882
5883/* ------------------------------ */
5884    .balign 64
5885.L_OP_USHR_INT_2ADDR: /* 0xba */
5886/* File: armv5te/OP_USHR_INT_2ADDR.S */
5887/* File: armv5te/binop2addr.S */
5888    /*
5889     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
5890     * that specifies an instruction that performs "result = r0 op r1".
5891     * This could be an ARM instruction or a function call.  (If the result
5892     * comes back in a register other than r0, you can override "result".)
5893     *
5894     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5895     * vCC (r1).  Useful for integer division and modulus.
5896     *
5897     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
5898     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
5899     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
5900     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
5901     */
5902    /* binop/2addr vA, vB */
5903    mov     r9, rINST, lsr #8           @ r9<- A+
5904    mov     r3, rINST, lsr #12          @ r3<- B
5905    and     r9, r9, #15
5906    GET_VREG(r1, r3)                    @ r1<- vB
5907    GET_VREG(r0, r9)                    @ r0<- vA
5908    .if 0
5909    cmp     r1, #0                      @ is second operand zero?
5910    beq     common_errDivideByZero
5911    .endif
5912    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5913
5914    and     r1, r1, #31                           @ optional op; may set condition codes
5915    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
5916    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5917    SET_VREG(r0, r9)               @ vAA<- r0
5918    GOTO_OPCODE(ip)                     @ jump to next instruction
5919    /* 10-13 instructions */
5920
5921
5922/* ------------------------------ */
5923    .balign 64
5924.L_OP_ADD_LONG_2ADDR: /* 0xbb */
5925/* File: armv5te/OP_ADD_LONG_2ADDR.S */
5926/* File: armv5te/binopWide2addr.S */
5927    /*
5928     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5929     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5930     * This could be an ARM instruction or a function call.  (If the result
5931     * comes back in a register other than r0, you can override "result".)
5932     *
5933     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5934     * vCC (r1).  Useful for integer division and modulus.
5935     *
5936     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5937     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5938     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5939     *      rem-double/2addr
5940     */
5941    /* binop/2addr vA, vB */
5942    mov     r9, rINST, lsr #8           @ r9<- A+
5943    mov     r1, rINST, lsr #12          @ r1<- B
5944    and     r9, r9, #15
5945    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5946    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5947    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5948    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5949    .if 0
5950    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5951    beq     common_errDivideByZero
5952    .endif
5953    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5954
5955    adds    r0, r0, r2                           @ optional op; may set condition codes
5956    adc     r1, r1, r3                              @ result<- op, r0-r3 changed
5957    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5958    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
5959    GOTO_OPCODE(ip)                     @ jump to next instruction
5960    /* 12-15 instructions */
5961
5962
5963/* ------------------------------ */
5964    .balign 64
5965.L_OP_SUB_LONG_2ADDR: /* 0xbc */
5966/* File: armv5te/OP_SUB_LONG_2ADDR.S */
5967/* File: armv5te/binopWide2addr.S */
5968    /*
5969     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
5970     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
5971     * This could be an ARM instruction or a function call.  (If the result
5972     * comes back in a register other than r0, you can override "result".)
5973     *
5974     * If "chkzero" is set to 1, we perform a divide-by-zero check on
5975     * vCC (r1).  Useful for integer division and modulus.
5976     *
5977     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
5978     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
5979     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
5980     *      rem-double/2addr
5981     */
5982    /* binop/2addr vA, vB */
5983    mov     r9, rINST, lsr #8           @ r9<- A+
5984    mov     r1, rINST, lsr #12          @ r1<- B
5985    and     r9, r9, #15
5986    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
5987    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
5988    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
5989    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
5990    .if 0
5991    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
5992    beq     common_errDivideByZero
5993    .endif
5994    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
5995
5996    subs    r0, r0, r2                           @ optional op; may set condition codes
5997    sbc     r1, r1, r3                              @ result<- op, r0-r3 changed
5998    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
5999    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6000    GOTO_OPCODE(ip)                     @ jump to next instruction
6001    /* 12-15 instructions */
6002
6003
6004/* ------------------------------ */
6005    .balign 64
6006.L_OP_MUL_LONG_2ADDR: /* 0xbd */
6007/* File: armv5te/OP_MUL_LONG_2ADDR.S */
6008    /*
6009     * Signed 64-bit integer multiply, "/2addr" version.
6010     *
6011     * See OP_MUL_LONG for an explanation.
6012     *
6013     * We get a little tight on registers, so to avoid looking up &fp[A]
6014     * again we stuff it into rINST.
6015     */
6016    /* mul-long/2addr vA, vB */
6017    mov     r9, rINST, lsr #8           @ r9<- A+
6018    mov     r1, rINST, lsr #12          @ r1<- B
6019    and     r9, r9, #15
6020    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6021    add     rINST, rFP, r9, lsl #2      @ rINST<- &fp[A]
6022    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6023    ldmia   rINST, {r0-r1}              @ r0/r1<- vAA/vAA+1
6024    mul     ip, r2, r1                  @  ip<- ZxW
6025    umull   r9, r10, r2, r0             @  r9/r10 <- ZxX
6026    mla     r2, r0, r3, ip              @  r2<- YxX + (ZxW)
6027    mov     r0, rINST                   @ r0<- &fp[A] (free up rINST)
6028    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6029    add     r10, r2, r10                @  r10<- r10 + low(ZxW + (YxX))
6030    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6031    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
6032    GOTO_OPCODE(ip)                     @ jump to next instruction
6033
6034/* ------------------------------ */
6035    .balign 64
6036.L_OP_DIV_LONG_2ADDR: /* 0xbe */
6037/* File: armv5te/OP_DIV_LONG_2ADDR.S */
6038/* File: armv5te/binopWide2addr.S */
6039    /*
6040     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6041     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6042     * This could be an ARM instruction or a function call.  (If the result
6043     * comes back in a register other than r0, you can override "result".)
6044     *
6045     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6046     * vCC (r1).  Useful for integer division and modulus.
6047     *
6048     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6049     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6050     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6051     *      rem-double/2addr
6052     */
6053    /* binop/2addr vA, vB */
6054    mov     r9, rINST, lsr #8           @ r9<- A+
6055    mov     r1, rINST, lsr #12          @ r1<- B
6056    and     r9, r9, #15
6057    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6058    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6059    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6060    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6061    .if 1
6062    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6063    beq     common_errDivideByZero
6064    .endif
6065    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6066
6067                               @ optional op; may set condition codes
6068    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6069    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6070    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6071    GOTO_OPCODE(ip)                     @ jump to next instruction
6072    /* 12-15 instructions */
6073
6074
6075/* ------------------------------ */
6076    .balign 64
6077.L_OP_REM_LONG_2ADDR: /* 0xbf */
6078/* File: armv5te/OP_REM_LONG_2ADDR.S */
6079/* ldivmod returns quotient in r0/r1 and remainder in r2/r3 */
6080/* File: armv5te/binopWide2addr.S */
6081    /*
6082     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6083     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6084     * This could be an ARM instruction or a function call.  (If the result
6085     * comes back in a register other than r0, you can override "result".)
6086     *
6087     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6088     * vCC (r1).  Useful for integer division and modulus.
6089     *
6090     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6091     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6092     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6093     *      rem-double/2addr
6094     */
6095    /* binop/2addr vA, vB */
6096    mov     r9, rINST, lsr #8           @ r9<- A+
6097    mov     r1, rINST, lsr #12          @ r1<- B
6098    and     r9, r9, #15
6099    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6100    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6101    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6102    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6103    .if 1
6104    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6105    beq     common_errDivideByZero
6106    .endif
6107    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6108
6109                               @ optional op; may set condition codes
6110    bl      __aeabi_ldivmod                              @ result<- op, r0-r3 changed
6111    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6112    stmia   r9, {r2,r3}     @ vAA/vAA+1<- r2/r3
6113    GOTO_OPCODE(ip)                     @ jump to next instruction
6114    /* 12-15 instructions */
6115
6116
6117/* ------------------------------ */
6118    .balign 64
6119.L_OP_AND_LONG_2ADDR: /* 0xc0 */
6120/* File: armv5te/OP_AND_LONG_2ADDR.S */
6121/* File: armv5te/binopWide2addr.S */
6122    /*
6123     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6124     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6125     * This could be an ARM instruction or a function call.  (If the result
6126     * comes back in a register other than r0, you can override "result".)
6127     *
6128     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6129     * vCC (r1).  Useful for integer division and modulus.
6130     *
6131     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6132     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6133     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6134     *      rem-double/2addr
6135     */
6136    /* binop/2addr vA, vB */
6137    mov     r9, rINST, lsr #8           @ r9<- A+
6138    mov     r1, rINST, lsr #12          @ r1<- B
6139    and     r9, r9, #15
6140    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6141    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6142    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6143    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6144    .if 0
6145    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6146    beq     common_errDivideByZero
6147    .endif
6148    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6149
6150    and     r0, r0, r2                           @ optional op; may set condition codes
6151    and     r1, r1, r3                              @ result<- op, r0-r3 changed
6152    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6153    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6154    GOTO_OPCODE(ip)                     @ jump to next instruction
6155    /* 12-15 instructions */
6156
6157
6158/* ------------------------------ */
6159    .balign 64
6160.L_OP_OR_LONG_2ADDR: /* 0xc1 */
6161/* File: armv5te/OP_OR_LONG_2ADDR.S */
6162/* File: armv5te/binopWide2addr.S */
6163    /*
6164     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6165     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6166     * This could be an ARM instruction or a function call.  (If the result
6167     * comes back in a register other than r0, you can override "result".)
6168     *
6169     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6170     * vCC (r1).  Useful for integer division and modulus.
6171     *
6172     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6173     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6174     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6175     *      rem-double/2addr
6176     */
6177    /* binop/2addr vA, vB */
6178    mov     r9, rINST, lsr #8           @ r9<- A+
6179    mov     r1, rINST, lsr #12          @ r1<- B
6180    and     r9, r9, #15
6181    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6182    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6183    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6184    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6185    .if 0
6186    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6187    beq     common_errDivideByZero
6188    .endif
6189    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6190
6191    orr     r0, r0, r2                           @ optional op; may set condition codes
6192    orr     r1, r1, r3                              @ result<- op, r0-r3 changed
6193    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6194    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6195    GOTO_OPCODE(ip)                     @ jump to next instruction
6196    /* 12-15 instructions */
6197
6198
6199/* ------------------------------ */
6200    .balign 64
6201.L_OP_XOR_LONG_2ADDR: /* 0xc2 */
6202/* File: armv5te/OP_XOR_LONG_2ADDR.S */
6203/* File: armv5te/binopWide2addr.S */
6204    /*
6205     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6206     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6207     * This could be an ARM instruction or a function call.  (If the result
6208     * comes back in a register other than r0, you can override "result".)
6209     *
6210     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6211     * vCC (r1).  Useful for integer division and modulus.
6212     *
6213     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6214     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6215     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6216     *      rem-double/2addr
6217     */
6218    /* binop/2addr vA, vB */
6219    mov     r9, rINST, lsr #8           @ r9<- A+
6220    mov     r1, rINST, lsr #12          @ r1<- B
6221    and     r9, r9, #15
6222    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6223    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6224    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6225    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6226    .if 0
6227    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6228    beq     common_errDivideByZero
6229    .endif
6230    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6231
6232    eor     r0, r0, r2                           @ optional op; may set condition codes
6233    eor     r1, r1, r3                              @ result<- op, r0-r3 changed
6234    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6235    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6236    GOTO_OPCODE(ip)                     @ jump to next instruction
6237    /* 12-15 instructions */
6238
6239
6240/* ------------------------------ */
6241    .balign 64
6242.L_OP_SHL_LONG_2ADDR: /* 0xc3 */
6243/* File: armv5te/OP_SHL_LONG_2ADDR.S */
6244    /*
6245     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6246     * 32-bit shift distance.
6247     */
6248    /* shl-long/2addr vA, vB */
6249    mov     r9, rINST, lsr #8           @ r9<- A+
6250    mov     r3, rINST, lsr #12          @ r3<- B
6251    and     r9, r9, #15
6252    GET_VREG(r2, r3)                    @ r2<- vB
6253    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6254    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6255    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6256
6257    mov     r1, r1, asl r2              @  r1<- r1 << r2
6258    rsb     r3, r2, #32                 @  r3<- 32 - r2
6259    orr     r1, r1, r0, lsr r3          @  r1<- r1 | (r0 << (32-r2))
6260    subs    ip, r2, #32                 @  ip<- r2 - 32
6261    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6262    movpl   r1, r0, asl ip              @  if r2 >= 32, r1<- r0 << (r2-32)
6263    mov     r0, r0, asl r2              @  r0<- r0 << r2
6264    b       .LOP_SHL_LONG_2ADDR_finish
6265
6266/* ------------------------------ */
6267    .balign 64
6268.L_OP_SHR_LONG_2ADDR: /* 0xc4 */
6269/* File: armv5te/OP_SHR_LONG_2ADDR.S */
6270    /*
6271     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6272     * 32-bit shift distance.
6273     */
6274    /* shr-long/2addr vA, vB */
6275    mov     r9, rINST, lsr #8           @ r9<- A+
6276    mov     r3, rINST, lsr #12          @ r3<- B
6277    and     r9, r9, #15
6278    GET_VREG(r2, r3)                    @ r2<- vB
6279    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6280    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6281    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6282
6283    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6284    rsb     r3, r2, #32                 @  r3<- 32 - r2
6285    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6286    subs    ip, r2, #32                 @  ip<- r2 - 32
6287    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6288    movpl   r0, r1, asr ip              @  if r2 >= 32, r0<-r1 >> (r2-32)
6289    mov     r1, r1, asr r2              @  r1<- r1 >> r2
6290    b       .LOP_SHR_LONG_2ADDR_finish
6291
6292/* ------------------------------ */
6293    .balign 64
6294.L_OP_USHR_LONG_2ADDR: /* 0xc5 */
6295/* File: armv5te/OP_USHR_LONG_2ADDR.S */
6296    /*
6297     * Long integer shift, 2addr version.  vA is 64-bit value/result, vB is
6298     * 32-bit shift distance.
6299     */
6300    /* ushr-long/2addr vA, vB */
6301    mov     r9, rINST, lsr #8           @ r9<- A+
6302    mov     r3, rINST, lsr #12          @ r3<- B
6303    and     r9, r9, #15
6304    GET_VREG(r2, r3)                    @ r2<- vB
6305    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6306    and     r2, r2, #63                 @ r2<- r2 & 0x3f
6307    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6308
6309    mov     r0, r0, lsr r2              @  r0<- r2 >> r2
6310    rsb     r3, r2, #32                 @  r3<- 32 - r2
6311    orr     r0, r0, r1, asl r3          @  r0<- r0 | (r1 << (32-r2))
6312    subs    ip, r2, #32                 @  ip<- r2 - 32
6313    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6314    movpl   r0, r1, lsr ip              @  if r2 >= 32, r0<-r1 >>> (r2-32)
6315    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
6316    b       .LOP_USHR_LONG_2ADDR_finish
6317
6318/* ------------------------------ */
6319    .balign 64
6320.L_OP_ADD_FLOAT_2ADDR: /* 0xc6 */
6321/* File: armv5te/OP_ADD_FLOAT_2ADDR.S */
6322/* File: armv5te/binop2addr.S */
6323    /*
6324     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6325     * that specifies an instruction that performs "result = r0 op r1".
6326     * This could be an ARM instruction or a function call.  (If the result
6327     * comes back in a register other than r0, you can override "result".)
6328     *
6329     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6330     * vCC (r1).  Useful for integer division and modulus.
6331     *
6332     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6333     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6334     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6335     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6336     */
6337    /* binop/2addr vA, vB */
6338    mov     r9, rINST, lsr #8           @ r9<- A+
6339    mov     r3, rINST, lsr #12          @ r3<- B
6340    and     r9, r9, #15
6341    GET_VREG(r1, r3)                    @ r1<- vB
6342    GET_VREG(r0, r9)                    @ r0<- vA
6343    .if 0
6344    cmp     r1, #0                      @ is second operand zero?
6345    beq     common_errDivideByZero
6346    .endif
6347    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6348
6349                               @ optional op; may set condition codes
6350    bl      __aeabi_fadd                              @ r0<- op, r0-r3 changed
6351    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6352    SET_VREG(r0, r9)               @ vAA<- r0
6353    GOTO_OPCODE(ip)                     @ jump to next instruction
6354    /* 10-13 instructions */
6355
6356
6357/* ------------------------------ */
6358    .balign 64
6359.L_OP_SUB_FLOAT_2ADDR: /* 0xc7 */
6360/* File: armv5te/OP_SUB_FLOAT_2ADDR.S */
6361/* File: armv5te/binop2addr.S */
6362    /*
6363     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6364     * that specifies an instruction that performs "result = r0 op r1".
6365     * This could be an ARM instruction or a function call.  (If the result
6366     * comes back in a register other than r0, you can override "result".)
6367     *
6368     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6369     * vCC (r1).  Useful for integer division and modulus.
6370     *
6371     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6372     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6373     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6374     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6375     */
6376    /* binop/2addr vA, vB */
6377    mov     r9, rINST, lsr #8           @ r9<- A+
6378    mov     r3, rINST, lsr #12          @ r3<- B
6379    and     r9, r9, #15
6380    GET_VREG(r1, r3)                    @ r1<- vB
6381    GET_VREG(r0, r9)                    @ r0<- vA
6382    .if 0
6383    cmp     r1, #0                      @ is second operand zero?
6384    beq     common_errDivideByZero
6385    .endif
6386    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6387
6388                               @ optional op; may set condition codes
6389    bl      __aeabi_fsub                              @ r0<- op, r0-r3 changed
6390    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6391    SET_VREG(r0, r9)               @ vAA<- r0
6392    GOTO_OPCODE(ip)                     @ jump to next instruction
6393    /* 10-13 instructions */
6394
6395
6396/* ------------------------------ */
6397    .balign 64
6398.L_OP_MUL_FLOAT_2ADDR: /* 0xc8 */
6399/* File: armv5te/OP_MUL_FLOAT_2ADDR.S */
6400/* File: armv5te/binop2addr.S */
6401    /*
6402     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6403     * that specifies an instruction that performs "result = r0 op r1".
6404     * This could be an ARM instruction or a function call.  (If the result
6405     * comes back in a register other than r0, you can override "result".)
6406     *
6407     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6408     * vCC (r1).  Useful for integer division and modulus.
6409     *
6410     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6411     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6412     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6413     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6414     */
6415    /* binop/2addr vA, vB */
6416    mov     r9, rINST, lsr #8           @ r9<- A+
6417    mov     r3, rINST, lsr #12          @ r3<- B
6418    and     r9, r9, #15
6419    GET_VREG(r1, r3)                    @ r1<- vB
6420    GET_VREG(r0, r9)                    @ r0<- vA
6421    .if 0
6422    cmp     r1, #0                      @ is second operand zero?
6423    beq     common_errDivideByZero
6424    .endif
6425    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6426
6427                               @ optional op; may set condition codes
6428    bl      __aeabi_fmul                              @ r0<- op, r0-r3 changed
6429    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6430    SET_VREG(r0, r9)               @ vAA<- r0
6431    GOTO_OPCODE(ip)                     @ jump to next instruction
6432    /* 10-13 instructions */
6433
6434
6435/* ------------------------------ */
6436    .balign 64
6437.L_OP_DIV_FLOAT_2ADDR: /* 0xc9 */
6438/* File: armv5te/OP_DIV_FLOAT_2ADDR.S */
6439/* File: armv5te/binop2addr.S */
6440    /*
6441     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6442     * that specifies an instruction that performs "result = r0 op r1".
6443     * This could be an ARM instruction or a function call.  (If the result
6444     * comes back in a register other than r0, you can override "result".)
6445     *
6446     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6447     * vCC (r1).  Useful for integer division and modulus.
6448     *
6449     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6450     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6451     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6452     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6453     */
6454    /* binop/2addr vA, vB */
6455    mov     r9, rINST, lsr #8           @ r9<- A+
6456    mov     r3, rINST, lsr #12          @ r3<- B
6457    and     r9, r9, #15
6458    GET_VREG(r1, r3)                    @ r1<- vB
6459    GET_VREG(r0, r9)                    @ r0<- vA
6460    .if 0
6461    cmp     r1, #0                      @ is second operand zero?
6462    beq     common_errDivideByZero
6463    .endif
6464    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6465
6466                               @ optional op; may set condition codes
6467    bl      __aeabi_fdiv                              @ r0<- op, r0-r3 changed
6468    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6469    SET_VREG(r0, r9)               @ vAA<- r0
6470    GOTO_OPCODE(ip)                     @ jump to next instruction
6471    /* 10-13 instructions */
6472
6473
6474/* ------------------------------ */
6475    .balign 64
6476.L_OP_REM_FLOAT_2ADDR: /* 0xca */
6477/* File: armv5te/OP_REM_FLOAT_2ADDR.S */
6478/* EABI doesn't define a float remainder function, but libm does */
6479/* File: armv5te/binop2addr.S */
6480    /*
6481     * Generic 32-bit "/2addr" binary operation.  Provide an "instr" line
6482     * that specifies an instruction that performs "result = r0 op r1".
6483     * This could be an ARM instruction or a function call.  (If the result
6484     * comes back in a register other than r0, you can override "result".)
6485     *
6486     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6487     * vCC (r1).  Useful for integer division and modulus.
6488     *
6489     * For: add-int/2addr, sub-int/2addr, mul-int/2addr, div-int/2addr,
6490     *      rem-int/2addr, and-int/2addr, or-int/2addr, xor-int/2addr,
6491     *      shl-int/2addr, shr-int/2addr, ushr-int/2addr, add-float/2addr,
6492     *      sub-float/2addr, mul-float/2addr, div-float/2addr, rem-float/2addr
6493     */
6494    /* binop/2addr vA, vB */
6495    mov     r9, rINST, lsr #8           @ r9<- A+
6496    mov     r3, rINST, lsr #12          @ r3<- B
6497    and     r9, r9, #15
6498    GET_VREG(r1, r3)                    @ r1<- vB
6499    GET_VREG(r0, r9)                    @ r0<- vA
6500    .if 0
6501    cmp     r1, #0                      @ is second operand zero?
6502    beq     common_errDivideByZero
6503    .endif
6504    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6505
6506                               @ optional op; may set condition codes
6507    bl      fmodf                              @ r0<- op, r0-r3 changed
6508    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6509    SET_VREG(r0, r9)               @ vAA<- r0
6510    GOTO_OPCODE(ip)                     @ jump to next instruction
6511    /* 10-13 instructions */
6512
6513
6514/* ------------------------------ */
6515    .balign 64
6516.L_OP_ADD_DOUBLE_2ADDR: /* 0xcb */
6517/* File: armv5te/OP_ADD_DOUBLE_2ADDR.S */
6518/* File: armv5te/binopWide2addr.S */
6519    /*
6520     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6521     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6522     * This could be an ARM instruction or a function call.  (If the result
6523     * comes back in a register other than r0, you can override "result".)
6524     *
6525     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6526     * vCC (r1).  Useful for integer division and modulus.
6527     *
6528     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6529     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6530     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6531     *      rem-double/2addr
6532     */
6533    /* binop/2addr vA, vB */
6534    mov     r9, rINST, lsr #8           @ r9<- A+
6535    mov     r1, rINST, lsr #12          @ r1<- B
6536    and     r9, r9, #15
6537    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6538    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6539    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6540    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6541    .if 0
6542    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6543    beq     common_errDivideByZero
6544    .endif
6545    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6546
6547                               @ optional op; may set condition codes
6548    bl      __aeabi_dadd                              @ result<- op, r0-r3 changed
6549    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6550    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6551    GOTO_OPCODE(ip)                     @ jump to next instruction
6552    /* 12-15 instructions */
6553
6554
6555/* ------------------------------ */
6556    .balign 64
6557.L_OP_SUB_DOUBLE_2ADDR: /* 0xcc */
6558/* File: armv5te/OP_SUB_DOUBLE_2ADDR.S */
6559/* File: armv5te/binopWide2addr.S */
6560    /*
6561     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6562     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6563     * This could be an ARM instruction or a function call.  (If the result
6564     * comes back in a register other than r0, you can override "result".)
6565     *
6566     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6567     * vCC (r1).  Useful for integer division and modulus.
6568     *
6569     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6570     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6571     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6572     *      rem-double/2addr
6573     */
6574    /* binop/2addr vA, vB */
6575    mov     r9, rINST, lsr #8           @ r9<- A+
6576    mov     r1, rINST, lsr #12          @ r1<- B
6577    and     r9, r9, #15
6578    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6579    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6580    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6581    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6582    .if 0
6583    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6584    beq     common_errDivideByZero
6585    .endif
6586    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6587
6588                               @ optional op; may set condition codes
6589    bl      __aeabi_dsub                              @ result<- op, r0-r3 changed
6590    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6591    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6592    GOTO_OPCODE(ip)                     @ jump to next instruction
6593    /* 12-15 instructions */
6594
6595
6596/* ------------------------------ */
6597    .balign 64
6598.L_OP_MUL_DOUBLE_2ADDR: /* 0xcd */
6599/* File: armv5te/OP_MUL_DOUBLE_2ADDR.S */
6600/* File: armv5te/binopWide2addr.S */
6601    /*
6602     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6603     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6604     * This could be an ARM instruction or a function call.  (If the result
6605     * comes back in a register other than r0, you can override "result".)
6606     *
6607     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6608     * vCC (r1).  Useful for integer division and modulus.
6609     *
6610     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6611     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6612     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6613     *      rem-double/2addr
6614     */
6615    /* binop/2addr vA, vB */
6616    mov     r9, rINST, lsr #8           @ r9<- A+
6617    mov     r1, rINST, lsr #12          @ r1<- B
6618    and     r9, r9, #15
6619    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6620    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6621    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6622    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6623    .if 0
6624    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6625    beq     common_errDivideByZero
6626    .endif
6627    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6628
6629                               @ optional op; may set condition codes
6630    bl      __aeabi_dmul                              @ result<- op, r0-r3 changed
6631    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6632    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6633    GOTO_OPCODE(ip)                     @ jump to next instruction
6634    /* 12-15 instructions */
6635
6636
6637/* ------------------------------ */
6638    .balign 64
6639.L_OP_DIV_DOUBLE_2ADDR: /* 0xce */
6640/* File: armv5te/OP_DIV_DOUBLE_2ADDR.S */
6641/* File: armv5te/binopWide2addr.S */
6642    /*
6643     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6644     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6645     * This could be an ARM instruction or a function call.  (If the result
6646     * comes back in a register other than r0, you can override "result".)
6647     *
6648     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6649     * vCC (r1).  Useful for integer division and modulus.
6650     *
6651     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6652     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6653     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6654     *      rem-double/2addr
6655     */
6656    /* binop/2addr vA, vB */
6657    mov     r9, rINST, lsr #8           @ r9<- A+
6658    mov     r1, rINST, lsr #12          @ r1<- B
6659    and     r9, r9, #15
6660    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6661    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6662    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6663    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6664    .if 0
6665    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6666    beq     common_errDivideByZero
6667    .endif
6668    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6669
6670                               @ optional op; may set condition codes
6671    bl      __aeabi_ddiv                              @ result<- op, r0-r3 changed
6672    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6673    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6674    GOTO_OPCODE(ip)                     @ jump to next instruction
6675    /* 12-15 instructions */
6676
6677
6678/* ------------------------------ */
6679    .balign 64
6680.L_OP_REM_DOUBLE_2ADDR: /* 0xcf */
6681/* File: armv5te/OP_REM_DOUBLE_2ADDR.S */
6682/* EABI doesn't define a double remainder function, but libm does */
6683/* File: armv5te/binopWide2addr.S */
6684    /*
6685     * Generic 64-bit "/2addr" binary operation.  Provide an "instr" line
6686     * that specifies an instruction that performs "result = r0-r1 op r2-r3".
6687     * This could be an ARM instruction or a function call.  (If the result
6688     * comes back in a register other than r0, you can override "result".)
6689     *
6690     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6691     * vCC (r1).  Useful for integer division and modulus.
6692     *
6693     * For: add-long/2addr, sub-long/2addr, div-long/2addr, rem-long/2addr,
6694     *      and-long/2addr, or-long/2addr, xor-long/2addr, add-double/2addr,
6695     *      sub-double/2addr, mul-double/2addr, div-double/2addr,
6696     *      rem-double/2addr
6697     */
6698    /* binop/2addr vA, vB */
6699    mov     r9, rINST, lsr #8           @ r9<- A+
6700    mov     r1, rINST, lsr #12          @ r1<- B
6701    and     r9, r9, #15
6702    add     r1, rFP, r1, lsl #2         @ r1<- &fp[B]
6703    add     r9, rFP, r9, lsl #2         @ r9<- &fp[A]
6704    ldmia   r1, {r2-r3}                 @ r2/r3<- vBB/vBB+1
6705    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
6706    .if 0
6707    orrs    ip, r2, r3                  @ second arg (r2-r3) is zero?
6708    beq     common_errDivideByZero
6709    .endif
6710    FETCH_ADVANCE_INST(1)               @ advance rPC, load rINST
6711
6712                               @ optional op; may set condition codes
6713    bl      fmod                              @ result<- op, r0-r3 changed
6714    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6715    stmia   r9, {r0,r1}     @ vAA/vAA+1<- r0/r1
6716    GOTO_OPCODE(ip)                     @ jump to next instruction
6717    /* 12-15 instructions */
6718
6719
6720/* ------------------------------ */
6721    .balign 64
6722.L_OP_ADD_INT_LIT16: /* 0xd0 */
6723/* File: armv5te/OP_ADD_INT_LIT16.S */
6724/* File: armv5te/binopLit16.S */
6725    /*
6726     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6727     * that specifies an instruction that performs "result = r0 op r1".
6728     * This could be an ARM instruction or a function call.  (If the result
6729     * comes back in a register other than r0, you can override "result".)
6730     *
6731     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6732     * vCC (r1).  Useful for integer division and modulus.
6733     *
6734     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6735     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6736     */
6737    /* binop/lit16 vA, vB, #+CCCC */
6738    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6739    mov     r2, rINST, lsr #12          @ r2<- B
6740    mov     r9, rINST, lsr #8           @ r9<- A+
6741    GET_VREG(r0, r2)                    @ r0<- vB
6742    and     r9, r9, #15
6743    .if 0
6744    cmp     r1, #0                      @ is second operand zero?
6745    beq     common_errDivideByZero
6746    .endif
6747    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6748
6749    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
6750    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6751    SET_VREG(r0, r9)               @ vAA<- r0
6752    GOTO_OPCODE(ip)                     @ jump to next instruction
6753    /* 10-13 instructions */
6754
6755
6756/* ------------------------------ */
6757    .balign 64
6758.L_OP_RSUB_INT: /* 0xd1 */
6759/* File: armv5te/OP_RSUB_INT.S */
6760/* this op is "rsub-int", but can be thought of as "rsub-int/lit16" */
6761/* File: armv5te/binopLit16.S */
6762    /*
6763     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6764     * that specifies an instruction that performs "result = r0 op r1".
6765     * This could be an ARM instruction or a function call.  (If the result
6766     * comes back in a register other than r0, you can override "result".)
6767     *
6768     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6769     * vCC (r1).  Useful for integer division and modulus.
6770     *
6771     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6772     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6773     */
6774    /* binop/lit16 vA, vB, #+CCCC */
6775    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6776    mov     r2, rINST, lsr #12          @ r2<- B
6777    mov     r9, rINST, lsr #8           @ r9<- A+
6778    GET_VREG(r0, r2)                    @ r0<- vB
6779    and     r9, r9, #15
6780    .if 0
6781    cmp     r1, #0                      @ is second operand zero?
6782    beq     common_errDivideByZero
6783    .endif
6784    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6785
6786    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
6787    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6788    SET_VREG(r0, r9)               @ vAA<- r0
6789    GOTO_OPCODE(ip)                     @ jump to next instruction
6790    /* 10-13 instructions */
6791
6792
6793/* ------------------------------ */
6794    .balign 64
6795.L_OP_MUL_INT_LIT16: /* 0xd2 */
6796/* File: armv5te/OP_MUL_INT_LIT16.S */
6797/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
6798/* File: armv5te/binopLit16.S */
6799    /*
6800     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6801     * that specifies an instruction that performs "result = r0 op r1".
6802     * This could be an ARM instruction or a function call.  (If the result
6803     * comes back in a register other than r0, you can override "result".)
6804     *
6805     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6806     * vCC (r1).  Useful for integer division and modulus.
6807     *
6808     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6809     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6810     */
6811    /* binop/lit16 vA, vB, #+CCCC */
6812    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6813    mov     r2, rINST, lsr #12          @ r2<- B
6814    mov     r9, rINST, lsr #8           @ r9<- A+
6815    GET_VREG(r0, r2)                    @ r0<- vB
6816    and     r9, r9, #15
6817    .if 0
6818    cmp     r1, #0                      @ is second operand zero?
6819    beq     common_errDivideByZero
6820    .endif
6821    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6822
6823    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
6824    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6825    SET_VREG(r0, r9)               @ vAA<- r0
6826    GOTO_OPCODE(ip)                     @ jump to next instruction
6827    /* 10-13 instructions */
6828
6829
6830/* ------------------------------ */
6831    .balign 64
6832.L_OP_DIV_INT_LIT16: /* 0xd3 */
6833/* File: armv5te/OP_DIV_INT_LIT16.S */
6834/* File: armv5te/binopLit16.S */
6835    /*
6836     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6837     * that specifies an instruction that performs "result = r0 op r1".
6838     * This could be an ARM instruction or a function call.  (If the result
6839     * comes back in a register other than r0, you can override "result".)
6840     *
6841     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6842     * vCC (r1).  Useful for integer division and modulus.
6843     *
6844     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6845     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6846     */
6847    /* binop/lit16 vA, vB, #+CCCC */
6848    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6849    mov     r2, rINST, lsr #12          @ r2<- B
6850    mov     r9, rINST, lsr #8           @ r9<- A+
6851    GET_VREG(r0, r2)                    @ r0<- vB
6852    and     r9, r9, #15
6853    .if 1
6854    cmp     r1, #0                      @ is second operand zero?
6855    beq     common_errDivideByZero
6856    .endif
6857    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6858
6859    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
6860    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6861    SET_VREG(r0, r9)               @ vAA<- r0
6862    GOTO_OPCODE(ip)                     @ jump to next instruction
6863    /* 10-13 instructions */
6864
6865
6866/* ------------------------------ */
6867    .balign 64
6868.L_OP_REM_INT_LIT16: /* 0xd4 */
6869/* File: armv5te/OP_REM_INT_LIT16.S */
6870/* idivmod returns quotient in r0 and remainder in r1 */
6871/* File: armv5te/binopLit16.S */
6872    /*
6873     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6874     * that specifies an instruction that performs "result = r0 op r1".
6875     * This could be an ARM instruction or a function call.  (If the result
6876     * comes back in a register other than r0, you can override "result".)
6877     *
6878     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6879     * vCC (r1).  Useful for integer division and modulus.
6880     *
6881     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6882     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6883     */
6884    /* binop/lit16 vA, vB, #+CCCC */
6885    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6886    mov     r2, rINST, lsr #12          @ r2<- B
6887    mov     r9, rINST, lsr #8           @ r9<- A+
6888    GET_VREG(r0, r2)                    @ r0<- vB
6889    and     r9, r9, #15
6890    .if 1
6891    cmp     r1, #0                      @ is second operand zero?
6892    beq     common_errDivideByZero
6893    .endif
6894    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6895
6896    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
6897    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6898    SET_VREG(r1, r9)               @ vAA<- r1
6899    GOTO_OPCODE(ip)                     @ jump to next instruction
6900    /* 10-13 instructions */
6901
6902
6903/* ------------------------------ */
6904    .balign 64
6905.L_OP_AND_INT_LIT16: /* 0xd5 */
6906/* File: armv5te/OP_AND_INT_LIT16.S */
6907/* File: armv5te/binopLit16.S */
6908    /*
6909     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6910     * that specifies an instruction that performs "result = r0 op r1".
6911     * This could be an ARM instruction or a function call.  (If the result
6912     * comes back in a register other than r0, you can override "result".)
6913     *
6914     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6915     * vCC (r1).  Useful for integer division and modulus.
6916     *
6917     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6918     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6919     */
6920    /* binop/lit16 vA, vB, #+CCCC */
6921    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6922    mov     r2, rINST, lsr #12          @ r2<- B
6923    mov     r9, rINST, lsr #8           @ r9<- A+
6924    GET_VREG(r0, r2)                    @ r0<- vB
6925    and     r9, r9, #15
6926    .if 0
6927    cmp     r1, #0                      @ is second operand zero?
6928    beq     common_errDivideByZero
6929    .endif
6930    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6931
6932    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
6933    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6934    SET_VREG(r0, r9)               @ vAA<- r0
6935    GOTO_OPCODE(ip)                     @ jump to next instruction
6936    /* 10-13 instructions */
6937
6938
6939/* ------------------------------ */
6940    .balign 64
6941.L_OP_OR_INT_LIT16: /* 0xd6 */
6942/* File: armv5te/OP_OR_INT_LIT16.S */
6943/* File: armv5te/binopLit16.S */
6944    /*
6945     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6946     * that specifies an instruction that performs "result = r0 op r1".
6947     * This could be an ARM instruction or a function call.  (If the result
6948     * comes back in a register other than r0, you can override "result".)
6949     *
6950     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6951     * vCC (r1).  Useful for integer division and modulus.
6952     *
6953     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6954     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6955     */
6956    /* binop/lit16 vA, vB, #+CCCC */
6957    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6958    mov     r2, rINST, lsr #12          @ r2<- B
6959    mov     r9, rINST, lsr #8           @ r9<- A+
6960    GET_VREG(r0, r2)                    @ r0<- vB
6961    and     r9, r9, #15
6962    .if 0
6963    cmp     r1, #0                      @ is second operand zero?
6964    beq     common_errDivideByZero
6965    .endif
6966    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
6967
6968    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
6969    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
6970    SET_VREG(r0, r9)               @ vAA<- r0
6971    GOTO_OPCODE(ip)                     @ jump to next instruction
6972    /* 10-13 instructions */
6973
6974
6975/* ------------------------------ */
6976    .balign 64
6977.L_OP_XOR_INT_LIT16: /* 0xd7 */
6978/* File: armv5te/OP_XOR_INT_LIT16.S */
6979/* File: armv5te/binopLit16.S */
6980    /*
6981     * Generic 32-bit "lit16" binary operation.  Provide an "instr" line
6982     * that specifies an instruction that performs "result = r0 op r1".
6983     * This could be an ARM instruction or a function call.  (If the result
6984     * comes back in a register other than r0, you can override "result".)
6985     *
6986     * If "chkzero" is set to 1, we perform a divide-by-zero check on
6987     * vCC (r1).  Useful for integer division and modulus.
6988     *
6989     * For: add-int/lit16, rsub-int, mul-int/lit16, div-int/lit16,
6990     *      rem-int/lit16, and-int/lit16, or-int/lit16, xor-int/lit16
6991     */
6992    /* binop/lit16 vA, vB, #+CCCC */
6993    FETCH_S(r1, 1)                      @ r1<- ssssCCCC (sign-extended)
6994    mov     r2, rINST, lsr #12          @ r2<- B
6995    mov     r9, rINST, lsr #8           @ r9<- A+
6996    GET_VREG(r0, r2)                    @ r0<- vB
6997    and     r9, r9, #15
6998    .if 0
6999    cmp     r1, #0                      @ is second operand zero?
7000    beq     common_errDivideByZero
7001    .endif
7002    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7003
7004    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7005    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7006    SET_VREG(r0, r9)               @ vAA<- r0
7007    GOTO_OPCODE(ip)                     @ jump to next instruction
7008    /* 10-13 instructions */
7009
7010
7011/* ------------------------------ */
7012    .balign 64
7013.L_OP_ADD_INT_LIT8: /* 0xd8 */
7014/* File: armv5te/OP_ADD_INT_LIT8.S */
7015/* File: armv5te/binopLit8.S */
7016    /*
7017     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7018     * that specifies an instruction that performs "result = r0 op r1".
7019     * This could be an ARM instruction or a function call.  (If the result
7020     * comes back in a register other than r0, you can override "result".)
7021     *
7022     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7023     * vCC (r1).  Useful for integer division and modulus.
7024     *
7025     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7026     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7027     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7028     */
7029    /* binop/lit8 vAA, vBB, #+CC */
7030    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7031    mov     r9, rINST, lsr #8           @ r9<- AA
7032    and     r2, r3, #255                @ r2<- BB
7033    GET_VREG(r0, r2)                    @ r0<- vBB
7034    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7035    .if 0
7036    @cmp     r1, #0                      @ is second operand zero?
7037    beq     common_errDivideByZero
7038    .endif
7039    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7040
7041                               @ optional op; may set condition codes
7042    add     r0, r0, r1                              @ r0<- op, r0-r3 changed
7043    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7044    SET_VREG(r0, r9)               @ vAA<- r0
7045    GOTO_OPCODE(ip)                     @ jump to next instruction
7046    /* 10-12 instructions */
7047
7048
7049/* ------------------------------ */
7050    .balign 64
7051.L_OP_RSUB_INT_LIT8: /* 0xd9 */
7052/* File: armv5te/OP_RSUB_INT_LIT8.S */
7053/* File: armv5te/binopLit8.S */
7054    /*
7055     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7056     * that specifies an instruction that performs "result = r0 op r1".
7057     * This could be an ARM instruction or a function call.  (If the result
7058     * comes back in a register other than r0, you can override "result".)
7059     *
7060     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7061     * vCC (r1).  Useful for integer division and modulus.
7062     *
7063     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7064     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7065     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7066     */
7067    /* binop/lit8 vAA, vBB, #+CC */
7068    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7069    mov     r9, rINST, lsr #8           @ r9<- AA
7070    and     r2, r3, #255                @ r2<- BB
7071    GET_VREG(r0, r2)                    @ r0<- vBB
7072    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7073    .if 0
7074    @cmp     r1, #0                      @ is second operand zero?
7075    beq     common_errDivideByZero
7076    .endif
7077    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7078
7079                               @ optional op; may set condition codes
7080    rsb     r0, r0, r1                              @ r0<- op, r0-r3 changed
7081    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7082    SET_VREG(r0, r9)               @ vAA<- r0
7083    GOTO_OPCODE(ip)                     @ jump to next instruction
7084    /* 10-12 instructions */
7085
7086
7087/* ------------------------------ */
7088    .balign 64
7089.L_OP_MUL_INT_LIT8: /* 0xda */
7090/* File: armv5te/OP_MUL_INT_LIT8.S */
7091/* must be "mul r0, r1, r0" -- "r0, r0, r1" is illegal */
7092/* File: armv5te/binopLit8.S */
7093    /*
7094     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7095     * that specifies an instruction that performs "result = r0 op r1".
7096     * This could be an ARM instruction or a function call.  (If the result
7097     * comes back in a register other than r0, you can override "result".)
7098     *
7099     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7100     * vCC (r1).  Useful for integer division and modulus.
7101     *
7102     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7103     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7104     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7105     */
7106    /* binop/lit8 vAA, vBB, #+CC */
7107    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7108    mov     r9, rINST, lsr #8           @ r9<- AA
7109    and     r2, r3, #255                @ r2<- BB
7110    GET_VREG(r0, r2)                    @ r0<- vBB
7111    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7112    .if 0
7113    @cmp     r1, #0                      @ is second operand zero?
7114    beq     common_errDivideByZero
7115    .endif
7116    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7117
7118                               @ optional op; may set condition codes
7119    mul     r0, r1, r0                              @ r0<- op, r0-r3 changed
7120    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7121    SET_VREG(r0, r9)               @ vAA<- r0
7122    GOTO_OPCODE(ip)                     @ jump to next instruction
7123    /* 10-12 instructions */
7124
7125
7126/* ------------------------------ */
7127    .balign 64
7128.L_OP_DIV_INT_LIT8: /* 0xdb */
7129/* File: armv5te/OP_DIV_INT_LIT8.S */
7130/* File: armv5te/binopLit8.S */
7131    /*
7132     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7133     * that specifies an instruction that performs "result = r0 op r1".
7134     * This could be an ARM instruction or a function call.  (If the result
7135     * comes back in a register other than r0, you can override "result".)
7136     *
7137     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7138     * vCC (r1).  Useful for integer division and modulus.
7139     *
7140     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7141     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7142     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7143     */
7144    /* binop/lit8 vAA, vBB, #+CC */
7145    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7146    mov     r9, rINST, lsr #8           @ r9<- AA
7147    and     r2, r3, #255                @ r2<- BB
7148    GET_VREG(r0, r2)                    @ r0<- vBB
7149    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7150    .if 1
7151    @cmp     r1, #0                      @ is second operand zero?
7152    beq     common_errDivideByZero
7153    .endif
7154    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7155
7156                               @ optional op; may set condition codes
7157    bl     __aeabi_idiv                              @ r0<- op, r0-r3 changed
7158    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7159    SET_VREG(r0, r9)               @ vAA<- r0
7160    GOTO_OPCODE(ip)                     @ jump to next instruction
7161    /* 10-12 instructions */
7162
7163
7164/* ------------------------------ */
7165    .balign 64
7166.L_OP_REM_INT_LIT8: /* 0xdc */
7167/* File: armv5te/OP_REM_INT_LIT8.S */
7168/* idivmod returns quotient in r0 and remainder in r1 */
7169/* File: armv5te/binopLit8.S */
7170    /*
7171     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7172     * that specifies an instruction that performs "result = r0 op r1".
7173     * This could be an ARM instruction or a function call.  (If the result
7174     * comes back in a register other than r0, you can override "result".)
7175     *
7176     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7177     * vCC (r1).  Useful for integer division and modulus.
7178     *
7179     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7180     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7181     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7182     */
7183    /* binop/lit8 vAA, vBB, #+CC */
7184    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7185    mov     r9, rINST, lsr #8           @ r9<- AA
7186    and     r2, r3, #255                @ r2<- BB
7187    GET_VREG(r0, r2)                    @ r0<- vBB
7188    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7189    .if 1
7190    @cmp     r1, #0                      @ is second operand zero?
7191    beq     common_errDivideByZero
7192    .endif
7193    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7194
7195                               @ optional op; may set condition codes
7196    bl      __aeabi_idivmod                              @ r1<- op, r0-r3 changed
7197    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7198    SET_VREG(r1, r9)               @ vAA<- r1
7199    GOTO_OPCODE(ip)                     @ jump to next instruction
7200    /* 10-12 instructions */
7201
7202
7203/* ------------------------------ */
7204    .balign 64
7205.L_OP_AND_INT_LIT8: /* 0xdd */
7206/* File: armv5te/OP_AND_INT_LIT8.S */
7207/* File: armv5te/binopLit8.S */
7208    /*
7209     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7210     * that specifies an instruction that performs "result = r0 op r1".
7211     * This could be an ARM instruction or a function call.  (If the result
7212     * comes back in a register other than r0, you can override "result".)
7213     *
7214     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7215     * vCC (r1).  Useful for integer division and modulus.
7216     *
7217     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7218     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7219     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7220     */
7221    /* binop/lit8 vAA, vBB, #+CC */
7222    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7223    mov     r9, rINST, lsr #8           @ r9<- AA
7224    and     r2, r3, #255                @ r2<- BB
7225    GET_VREG(r0, r2)                    @ r0<- vBB
7226    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7227    .if 0
7228    @cmp     r1, #0                      @ is second operand zero?
7229    beq     common_errDivideByZero
7230    .endif
7231    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7232
7233                               @ optional op; may set condition codes
7234    and     r0, r0, r1                              @ r0<- op, r0-r3 changed
7235    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7236    SET_VREG(r0, r9)               @ vAA<- r0
7237    GOTO_OPCODE(ip)                     @ jump to next instruction
7238    /* 10-12 instructions */
7239
7240
7241/* ------------------------------ */
7242    .balign 64
7243.L_OP_OR_INT_LIT8: /* 0xde */
7244/* File: armv5te/OP_OR_INT_LIT8.S */
7245/* File: armv5te/binopLit8.S */
7246    /*
7247     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7248     * that specifies an instruction that performs "result = r0 op r1".
7249     * This could be an ARM instruction or a function call.  (If the result
7250     * comes back in a register other than r0, you can override "result".)
7251     *
7252     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7253     * vCC (r1).  Useful for integer division and modulus.
7254     *
7255     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7256     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7257     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7258     */
7259    /* binop/lit8 vAA, vBB, #+CC */
7260    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7261    mov     r9, rINST, lsr #8           @ r9<- AA
7262    and     r2, r3, #255                @ r2<- BB
7263    GET_VREG(r0, r2)                    @ r0<- vBB
7264    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7265    .if 0
7266    @cmp     r1, #0                      @ is second operand zero?
7267    beq     common_errDivideByZero
7268    .endif
7269    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7270
7271                               @ optional op; may set condition codes
7272    orr     r0, r0, r1                              @ r0<- op, r0-r3 changed
7273    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7274    SET_VREG(r0, r9)               @ vAA<- r0
7275    GOTO_OPCODE(ip)                     @ jump to next instruction
7276    /* 10-12 instructions */
7277
7278
7279/* ------------------------------ */
7280    .balign 64
7281.L_OP_XOR_INT_LIT8: /* 0xdf */
7282/* File: armv5te/OP_XOR_INT_LIT8.S */
7283/* File: armv5te/binopLit8.S */
7284    /*
7285     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7286     * that specifies an instruction that performs "result = r0 op r1".
7287     * This could be an ARM instruction or a function call.  (If the result
7288     * comes back in a register other than r0, you can override "result".)
7289     *
7290     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7291     * vCC (r1).  Useful for integer division and modulus.
7292     *
7293     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7294     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7295     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7296     */
7297    /* binop/lit8 vAA, vBB, #+CC */
7298    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7299    mov     r9, rINST, lsr #8           @ r9<- AA
7300    and     r2, r3, #255                @ r2<- BB
7301    GET_VREG(r0, r2)                    @ r0<- vBB
7302    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7303    .if 0
7304    @cmp     r1, #0                      @ is second operand zero?
7305    beq     common_errDivideByZero
7306    .endif
7307    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7308
7309                               @ optional op; may set condition codes
7310    eor     r0, r0, r1                              @ r0<- op, r0-r3 changed
7311    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7312    SET_VREG(r0, r9)               @ vAA<- r0
7313    GOTO_OPCODE(ip)                     @ jump to next instruction
7314    /* 10-12 instructions */
7315
7316
7317/* ------------------------------ */
7318    .balign 64
7319.L_OP_SHL_INT_LIT8: /* 0xe0 */
7320/* File: armv5te/OP_SHL_INT_LIT8.S */
7321/* File: armv5te/binopLit8.S */
7322    /*
7323     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7324     * that specifies an instruction that performs "result = r0 op r1".
7325     * This could be an ARM instruction or a function call.  (If the result
7326     * comes back in a register other than r0, you can override "result".)
7327     *
7328     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7329     * vCC (r1).  Useful for integer division and modulus.
7330     *
7331     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7332     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7333     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7334     */
7335    /* binop/lit8 vAA, vBB, #+CC */
7336    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7337    mov     r9, rINST, lsr #8           @ r9<- AA
7338    and     r2, r3, #255                @ r2<- BB
7339    GET_VREG(r0, r2)                    @ r0<- vBB
7340    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7341    .if 0
7342    @cmp     r1, #0                      @ is second operand zero?
7343    beq     common_errDivideByZero
7344    .endif
7345    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7346
7347    and     r1, r1, #31                           @ optional op; may set condition codes
7348    mov     r0, r0, asl r1                              @ r0<- op, r0-r3 changed
7349    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7350    SET_VREG(r0, r9)               @ vAA<- r0
7351    GOTO_OPCODE(ip)                     @ jump to next instruction
7352    /* 10-12 instructions */
7353
7354
7355/* ------------------------------ */
7356    .balign 64
7357.L_OP_SHR_INT_LIT8: /* 0xe1 */
7358/* File: armv5te/OP_SHR_INT_LIT8.S */
7359/* File: armv5te/binopLit8.S */
7360    /*
7361     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7362     * that specifies an instruction that performs "result = r0 op r1".
7363     * This could be an ARM instruction or a function call.  (If the result
7364     * comes back in a register other than r0, you can override "result".)
7365     *
7366     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7367     * vCC (r1).  Useful for integer division and modulus.
7368     *
7369     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7370     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7371     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7372     */
7373    /* binop/lit8 vAA, vBB, #+CC */
7374    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7375    mov     r9, rINST, lsr #8           @ r9<- AA
7376    and     r2, r3, #255                @ r2<- BB
7377    GET_VREG(r0, r2)                    @ r0<- vBB
7378    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7379    .if 0
7380    @cmp     r1, #0                      @ is second operand zero?
7381    beq     common_errDivideByZero
7382    .endif
7383    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7384
7385    and     r1, r1, #31                           @ optional op; may set condition codes
7386    mov     r0, r0, asr r1                              @ r0<- op, r0-r3 changed
7387    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7388    SET_VREG(r0, r9)               @ vAA<- r0
7389    GOTO_OPCODE(ip)                     @ jump to next instruction
7390    /* 10-12 instructions */
7391
7392
7393/* ------------------------------ */
7394    .balign 64
7395.L_OP_USHR_INT_LIT8: /* 0xe2 */
7396/* File: armv5te/OP_USHR_INT_LIT8.S */
7397/* File: armv5te/binopLit8.S */
7398    /*
7399     * Generic 32-bit "lit8" binary operation.  Provide an "instr" line
7400     * that specifies an instruction that performs "result = r0 op r1".
7401     * This could be an ARM instruction or a function call.  (If the result
7402     * comes back in a register other than r0, you can override "result".)
7403     *
7404     * If "chkzero" is set to 1, we perform a divide-by-zero check on
7405     * vCC (r1).  Useful for integer division and modulus.
7406     *
7407     * For: add-int/lit8, rsub-int/lit8, mul-int/lit8, div-int/lit8,
7408     *      rem-int/lit8, and-int/lit8, or-int/lit8, xor-int/lit8,
7409     *      shl-int/lit8, shr-int/lit8, ushr-int/lit8
7410     */
7411    /* binop/lit8 vAA, vBB, #+CC */
7412    FETCH_S(r3, 1)                      @ r3<- ssssCCBB (sign-extended for CC)
7413    mov     r9, rINST, lsr #8           @ r9<- AA
7414    and     r2, r3, #255                @ r2<- BB
7415    GET_VREG(r0, r2)                    @ r0<- vBB
7416    movs    r1, r3, asr #8              @ r1<- ssssssCC (sign extended)
7417    .if 0
7418    @cmp     r1, #0                      @ is second operand zero?
7419    beq     common_errDivideByZero
7420    .endif
7421    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7422
7423    and     r1, r1, #31                           @ optional op; may set condition codes
7424    mov     r0, r0, lsr r1                              @ r0<- op, r0-r3 changed
7425    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7426    SET_VREG(r0, r9)               @ vAA<- r0
7427    GOTO_OPCODE(ip)                     @ jump to next instruction
7428    /* 10-12 instructions */
7429
7430
7431/* ------------------------------ */
7432    .balign 64
7433.L_OP_IGET_VOLATILE: /* 0xe3 */
7434/* File: armv5te/OP_IGET_VOLATILE.S */
7435/* File: armv5te/OP_IGET.S */
7436    /*
7437     * General 32-bit instance field get.
7438     *
7439     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7440     */
7441    /* op vA, vB, field@CCCC */
7442    mov     r0, rINST, lsr #12          @ r0<- B
7443    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7444    FETCH(r1, 1)                        @ r1<- field ref CCCC
7445    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7446    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7447    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7448    cmp     r0, #0                      @ is resolved entry null?
7449    bne     .LOP_IGET_VOLATILE_finish          @ no, already resolved
74508:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7451    EXPORT_PC()                         @ resolve() could throw
7452    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7453    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7454    cmp     r0, #0
7455    bne     .LOP_IGET_VOLATILE_finish
7456    b       common_exceptionThrown
7457
7458
7459/* ------------------------------ */
7460    .balign 64
7461.L_OP_IPUT_VOLATILE: /* 0xe4 */
7462/* File: armv5te/OP_IPUT_VOLATILE.S */
7463/* File: armv5te/OP_IPUT.S */
7464    /*
7465     * General 32-bit instance field put.
7466     *
7467     * for: iput, iput-boolean, iput-byte, iput-char, iput-short
7468     */
7469    /* op vA, vB, field@CCCC */
7470    mov     r0, rINST, lsr #12          @ r0<- B
7471    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7472    FETCH(r1, 1)                        @ r1<- field ref CCCC
7473    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7474    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7475    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7476    cmp     r0, #0                      @ is resolved entry null?
7477    bne     .LOP_IPUT_VOLATILE_finish          @ no, already resolved
74788:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7479    EXPORT_PC()                         @ resolve() could throw
7480    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7481    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7482    cmp     r0, #0                      @ success?
7483    bne     .LOP_IPUT_VOLATILE_finish          @ yes, finish up
7484    b       common_exceptionThrown
7485
7486
7487/* ------------------------------ */
7488    .balign 64
7489.L_OP_SGET_VOLATILE: /* 0xe5 */
7490/* File: armv5te/OP_SGET_VOLATILE.S */
7491/* File: armv5te/OP_SGET.S */
7492    /*
7493     * General 32-bit SGET handler.
7494     *
7495     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
7496     */
7497    /* op vAA, field@BBBB */
7498    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7499    FETCH(r1, 1)                        @ r1<- field ref BBBB
7500    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7501    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7502    cmp     r0, #0                      @ is resolved entry null?
7503    beq     .LOP_SGET_VOLATILE_resolve         @ yes, do resolve
7504.LOP_SGET_VOLATILE_finish: @ field ptr in r0
7505    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
7506    SMP_DMB                            @ acquiring load
7507    mov     r2, rINST, lsr #8           @ r2<- AA
7508    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7509    SET_VREG(r1, r2)                    @ fp[AA]<- r1
7510    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7511    GOTO_OPCODE(ip)                     @ jump to next instruction
7512
7513
7514/* ------------------------------ */
7515    .balign 64
7516.L_OP_SPUT_VOLATILE: /* 0xe6 */
7517/* File: armv5te/OP_SPUT_VOLATILE.S */
7518/* File: armv5te/OP_SPUT.S */
7519    /*
7520     * General 32-bit SPUT handler.
7521     *
7522     * for: sput, sput-boolean, sput-byte, sput-char, sput-short
7523     */
7524    /* op vAA, field@BBBB */
7525    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7526    FETCH(r1, 1)                        @ r1<- field ref BBBB
7527    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7528    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7529    cmp     r0, #0                      @ is resolved entry null?
7530    beq     .LOP_SPUT_VOLATILE_resolve         @ yes, do resolve
7531.LOP_SPUT_VOLATILE_finish:   @ field ptr in r0
7532    mov     r2, rINST, lsr #8           @ r2<- AA
7533    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7534    GET_VREG(r1, r2)                    @ r1<- fp[AA]
7535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7536    SMP_DMB                            @ releasing store
7537    str     r1, [r0, #offStaticField_value] @ field<- vAA
7538    GOTO_OPCODE(ip)                     @ jump to next instruction
7539
7540
7541/* ------------------------------ */
7542    .balign 64
7543.L_OP_IGET_OBJECT_VOLATILE: /* 0xe7 */
7544/* File: armv5te/OP_IGET_OBJECT_VOLATILE.S */
7545/* File: armv5te/OP_IGET.S */
7546    /*
7547     * General 32-bit instance field get.
7548     *
7549     * for: iget, iget-object, iget-boolean, iget-byte, iget-char, iget-short
7550     */
7551    /* op vA, vB, field@CCCC */
7552    mov     r0, rINST, lsr #12          @ r0<- B
7553    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7554    FETCH(r1, 1)                        @ r1<- field ref CCCC
7555    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
7556    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7557    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7558    cmp     r0, #0                      @ is resolved entry null?
7559    bne     .LOP_IGET_OBJECT_VOLATILE_finish          @ no, already resolved
75608:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7561    EXPORT_PC()                         @ resolve() could throw
7562    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7563    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7564    cmp     r0, #0
7565    bne     .LOP_IGET_OBJECT_VOLATILE_finish
7566    b       common_exceptionThrown
7567
7568
7569/* ------------------------------ */
7570    .balign 64
7571.L_OP_IGET_WIDE_VOLATILE: /* 0xe8 */
7572/* File: armv4t/OP_IGET_WIDE_VOLATILE.S */
7573/* File: armv4t/OP_IGET_WIDE.S */
7574    /*
7575     * Wide 32-bit instance field get.
7576     */
7577    /* iget-wide vA, vB, field@CCCC */
7578    mov     r0, rINST, lsr #12          @ r0<- B
7579    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7580    FETCH(r1, 1)                        @ r1<- field ref CCCC
7581    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7582    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7583    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7584    cmp     r0, #0                      @ is resolved entry null?
7585    bne     .LOP_IGET_WIDE_VOLATILE_finish          @ no, already resolved
75868:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7587    EXPORT_PC()                         @ resolve() could throw
7588    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7589    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7590    cmp     r0, #0
7591    bne     .LOP_IGET_WIDE_VOLATILE_finish
7592    b       common_exceptionThrown
7593
7594
7595/* ------------------------------ */
7596    .balign 64
7597.L_OP_IPUT_WIDE_VOLATILE: /* 0xe9 */
7598/* File: armv4t/OP_IPUT_WIDE_VOLATILE.S */
7599/* File: armv4t/OP_IPUT_WIDE.S */
7600    /* iput-wide vA, vB, field@CCCC */
7601    mov     r0, rINST, lsr #12          @ r0<- B
7602    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
7603    FETCH(r1, 1)                        @ r1<- field ref CCCC
7604    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pResFields
7605    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
7606    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
7607    cmp     r0, #0                      @ is resolved entry null?
7608    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ no, already resolved
76098:  ldr     r2, [rGLUE, #offGlue_method] @ r2<- current method
7610    EXPORT_PC()                         @ resolve() could throw
7611    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
7612    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
7613    cmp     r0, #0                      @ success?
7614    bne     .LOP_IPUT_WIDE_VOLATILE_finish          @ yes, finish up
7615    b       common_exceptionThrown
7616
7617
7618/* ------------------------------ */
7619    .balign 64
7620.L_OP_SGET_WIDE_VOLATILE: /* 0xea */
7621/* File: armv4t/OP_SGET_WIDE_VOLATILE.S */
7622/* File: armv4t/OP_SGET_WIDE.S */
7623    /*
7624     * 64-bit SGET handler.
7625     */
7626    /* sget-wide vAA, field@BBBB */
7627    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
7628    FETCH(r1, 1)                        @ r1<- field ref BBBB
7629    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
7630    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
7631    cmp     r0, #0                      @ is resolved entry null?
7632    beq     .LOP_SGET_WIDE_VOLATILE_resolve         @ yes, do resolve
7633.LOP_SGET_WIDE_VOLATILE_finish:
7634    mov     r9, rINST, lsr #8           @ r9<- AA
7635    add     r0, r0, #offStaticField_value @ r0<- pointer to data
7636    .if 1
7637    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
7638    .else
7639    ldmia   r0, {r0-r1}                 @ r0/r1<- field value (aligned)
7640    .endif
7641    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7642    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7643    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
7644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7645    GOTO_OPCODE(ip)                     @ jump to next instruction
7646
7647
7648/* ------------------------------ */
7649    .balign 64
7650.L_OP_SPUT_WIDE_VOLATILE: /* 0xeb */
7651/* File: armv4t/OP_SPUT_WIDE_VOLATILE.S */
7652/* File: armv4t/OP_SPUT_WIDE.S */
7653    /*
7654     * 64-bit SPUT handler.
7655     */
7656    /* sput-wide vAA, field@BBBB */
7657    ldr     r0, [rGLUE, #offGlue_methodClassDex]    @ r0<- DvmDex
7658    FETCH(r1, 1)                        @ r1<- field ref BBBB
7659    ldr     r0, [r0, #offDvmDex_pResFields] @ r0<- dvmDex->pResFields
7660    mov     r9, rINST, lsr #8           @ r9<- AA
7661    ldr     r2, [r0, r1, lsl #2]        @ r2<- resolved StaticField ptr
7662    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
7663    cmp     r2, #0                      @ is resolved entry null?
7664    beq     .LOP_SPUT_WIDE_VOLATILE_resolve         @ yes, do resolve
7665.LOP_SPUT_WIDE_VOLATILE_finish: @ field ptr in r2, AA in r9
7666    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7667    ldmia   r9, {r0-r1}                 @ r0/r1<- vAA/vAA+1
7668    GET_INST_OPCODE(r10)                @ extract opcode from rINST
7669    add     r2, r2, #offStaticField_value @ r2<- pointer to data
7670    .if 1
7671    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
7672    .else
7673    stmia   r2, {r0-r1}                 @ field<- vAA/vAA+1
7674    .endif
7675    GOTO_OPCODE(r10)                    @ jump to next instruction
7676
7677
7678/* ------------------------------ */
7679    .balign 64
7680.L_OP_BREAKPOINT: /* 0xec */
7681/* File: armv5te/OP_BREAKPOINT.S */
7682/* File: armv5te/unused.S */
7683    bl      common_abort
7684
7685
7686/* ------------------------------ */
7687    .balign 64
7688.L_OP_THROW_VERIFICATION_ERROR: /* 0xed */
7689/* File: armv5te/OP_THROW_VERIFICATION_ERROR.S */
7690    /*
7691     * Handle a throw-verification-error instruction.  This throws an
7692     * exception for an error discovered during verification.  The
7693     * exception is indicated by AA, with some detail provided by BBBB.
7694     */
7695    /* op AA, ref@BBBB */
7696    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
7697    FETCH(r2, 1)                        @ r2<- BBBB
7698    EXPORT_PC()                         @ export the PC
7699    mov     r1, rINST, lsr #8           @ r1<- AA
7700    bl      dvmThrowVerificationError   @ always throws
7701    b       common_exceptionThrown      @ handle exception
7702
7703/* ------------------------------ */
7704    .balign 64
7705.L_OP_EXECUTE_INLINE: /* 0xee */
7706/* File: armv5te/OP_EXECUTE_INLINE.S */
7707    /*
7708     * Execute a "native inline" instruction.
7709     *
7710     * We need to call an InlineOp4Func:
7711     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7712     *
7713     * The first four args are in r0-r3, pointer to return value storage
7714     * is on the stack.  The function's return value is a flag that tells
7715     * us if an exception was thrown.
7716     */
7717    /* [opt] execute-inline vAA, {vC, vD, vE, vF}, inline@BBBB */
7718    FETCH(r10, 1)                       @ r10<- BBBB
7719    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7720    EXPORT_PC()                         @ can throw
7721    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7722    mov     r0, rINST, lsr #12          @ r0<- B
7723    str     r1, [sp]                    @ push &glue->retval
7724    bl      .LOP_EXECUTE_INLINE_continue        @ make call; will return after
7725    add     sp, sp, #8                  @ pop stack
7726    cmp     r0, #0                      @ test boolean result of inline
7727    beq     common_exceptionThrown      @ returned false, handle exception
7728    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7729    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7730    GOTO_OPCODE(ip)                     @ jump to next instruction
7731
7732/* ------------------------------ */
7733    .balign 64
7734.L_OP_EXECUTE_INLINE_RANGE: /* 0xef */
7735/* File: armv5te/OP_EXECUTE_INLINE_RANGE.S */
7736    /*
7737     * Execute a "native inline" instruction, using "/range" semantics.
7738     * Same idea as execute-inline, but we get the args differently.
7739     *
7740     * We need to call an InlineOp4Func:
7741     *  bool (func)(u4 arg0, u4 arg1, u4 arg2, u4 arg3, JValue* pResult)
7742     *
7743     * The first four args are in r0-r3, pointer to return value storage
7744     * is on the stack.  The function's return value is a flag that tells
7745     * us if an exception was thrown.
7746     */
7747    /* [opt] execute-inline/range {vCCCC..v(CCCC+AA-1)}, inline@BBBB */
7748    FETCH(r10, 1)                       @ r10<- BBBB
7749    add     r1, rGLUE, #offGlue_retval  @ r1<- &glue->retval
7750    EXPORT_PC()                         @ can throw
7751    sub     sp, sp, #8                  @ make room for arg, +64 bit align
7752    mov     r0, rINST, lsr #8           @ r0<- AA
7753    str     r1, [sp]                    @ push &glue->retval
7754    bl      .LOP_EXECUTE_INLINE_RANGE_continue        @ make call; will return after
7755    add     sp, sp, #8                  @ pop stack
7756    cmp     r0, #0                      @ test boolean result of inline
7757    beq     common_exceptionThrown      @ returned false, handle exception
7758    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
7759    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7760    GOTO_OPCODE(ip)                     @ jump to next instruction
7761
7762/* ------------------------------ */
7763    .balign 64
7764.L_OP_INVOKE_DIRECT_EMPTY: /* 0xf0 */
7765/* File: armv5te/OP_INVOKE_DIRECT_EMPTY.S */
7766    /*
7767     * invoke-direct-empty is a no-op in a "standard" interpreter.
7768     */
7769    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
7770    GET_INST_OPCODE(ip)                 @ ip<- opcode from rINST
7771    GOTO_OPCODE(ip)                     @ execute it
7772
7773/* ------------------------------ */
7774    .balign 64
7775.L_OP_UNUSED_F1: /* 0xf1 */
7776/* File: armv5te/OP_UNUSED_F1.S */
7777/* File: armv5te/unused.S */
7778    bl      common_abort
7779
7780
7781/* ------------------------------ */
7782    .balign 64
7783.L_OP_IGET_QUICK: /* 0xf2 */
7784/* File: armv5te/OP_IGET_QUICK.S */
7785    /* For: iget-quick, iget-object-quick */
7786    /* op vA, vB, offset@CCCC */
7787    mov     r2, rINST, lsr #12          @ r2<- B
7788    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7789    FETCH(r1, 1)                        @ r1<- field byte offset
7790    cmp     r3, #0                      @ check object for null
7791    mov     r2, rINST, lsr #8           @ r2<- A(+)
7792    beq     common_errNullObject        @ object was null
7793    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7794    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7795    and     r2, r2, #15
7796    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7797    SET_VREG(r0, r2)                    @ fp[A]<- r0
7798    GOTO_OPCODE(ip)                     @ jump to next instruction
7799
7800/* ------------------------------ */
7801    .balign 64
7802.L_OP_IGET_WIDE_QUICK: /* 0xf3 */
7803/* File: armv4t/OP_IGET_WIDE_QUICK.S */
7804    /* iget-wide-quick vA, vB, offset@CCCC */
7805    mov     r2, rINST, lsr #12          @ r2<- B
7806    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7807    FETCH(r1, 1)                        @ r1<- field byte offset
7808    cmp     r3, #0                      @ check object for null
7809    mov     r2, rINST, lsr #8           @ r2<- A(+)
7810    beq     common_errNullObject        @ object was null
7811    add     r9, r3, r1                  @ r9<- object + offset
7812    ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64 bits, aligned)
7813    and     r2, r2, #15                 @ r2<- A
7814    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7815    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
7816    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7817    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
7818    GOTO_OPCODE(ip)                     @ jump to next instruction
7819
7820/* ------------------------------ */
7821    .balign 64
7822.L_OP_IGET_OBJECT_QUICK: /* 0xf4 */
7823/* File: armv5te/OP_IGET_OBJECT_QUICK.S */
7824/* File: armv5te/OP_IGET_QUICK.S */
7825    /* For: iget-quick, iget-object-quick */
7826    /* op vA, vB, offset@CCCC */
7827    mov     r2, rINST, lsr #12          @ r2<- B
7828    GET_VREG(r3, r2)                    @ r3<- object we're operating on
7829    FETCH(r1, 1)                        @ r1<- field byte offset
7830    cmp     r3, #0                      @ check object for null
7831    mov     r2, rINST, lsr #8           @ r2<- A(+)
7832    beq     common_errNullObject        @ object was null
7833    ldr     r0, [r3, r1]                @ r0<- obj.field (always 32 bits)
7834    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7835    and     r2, r2, #15
7836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7837    SET_VREG(r0, r2)                    @ fp[A]<- r0
7838    GOTO_OPCODE(ip)                     @ jump to next instruction
7839
7840
7841/* ------------------------------ */
7842    .balign 64
7843.L_OP_IPUT_QUICK: /* 0xf5 */
7844/* File: armv5te/OP_IPUT_QUICK.S */
7845    /* For: iput-quick */
7846    /* op vA, vB, offset@CCCC */
7847    mov     r2, rINST, lsr #12          @ r2<- B
7848    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7849    FETCH(r1, 1)                        @ r1<- field byte offset
7850    cmp     r3, #0                      @ check object for null
7851    mov     r2, rINST, lsr #8           @ r2<- A(+)
7852    beq     common_errNullObject        @ object was null
7853    and     r2, r2, #15
7854    GET_VREG(r0, r2)                    @ r0<- fp[A]
7855    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7856    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7857    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7858    GOTO_OPCODE(ip)                     @ jump to next instruction
7859
7860/* ------------------------------ */
7861    .balign 64
7862.L_OP_IPUT_WIDE_QUICK: /* 0xf6 */
7863/* File: armv4t/OP_IPUT_WIDE_QUICK.S */
7864    /* iput-wide-quick vA, vB, offset@CCCC */
7865    mov     r0, rINST, lsr #8           @ r0<- A(+)
7866    mov     r1, rINST, lsr #12          @ r1<- B
7867    and     r0, r0, #15
7868    GET_VREG(r2, r1)                    @ r2<- fp[B], the object pointer
7869    add     r3, rFP, r0, lsl #2         @ r3<- &fp[A]
7870    cmp     r2, #0                      @ check object for null
7871    ldmia   r3, {r0-r1}                 @ r0/r1<- fp[A]
7872    beq     common_errNullObject        @ object was null
7873    FETCH(r3, 1)                        @ r3<- field byte offset
7874    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7875    add     r2, r2, r3                  @ r2<- object + byte offset
7876    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
7877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7878    GOTO_OPCODE(ip)                     @ jump to next instruction
7879
7880/* ------------------------------ */
7881    .balign 64
7882.L_OP_IPUT_OBJECT_QUICK: /* 0xf7 */
7883/* File: armv5te/OP_IPUT_OBJECT_QUICK.S */
7884    /* For: iput-object-quick */
7885    /* op vA, vB, offset@CCCC */
7886    mov     r2, rINST, lsr #12          @ r2<- B
7887    GET_VREG(r3, r2)                    @ r3<- fp[B], the object pointer
7888    FETCH(r1, 1)                        @ r1<- field byte offset
7889    cmp     r3, #0                      @ check object for null
7890    mov     r2, rINST, lsr #8           @ r2<- A(+)
7891    beq     common_errNullObject        @ object was null
7892    and     r2, r2, #15
7893    GET_VREG(r0, r2)                    @ r0<- fp[A]
7894    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
7895    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
7896    str     r0, [r3, r1]                @ obj.field (always 32 bits)<- r0
7897    cmp     r0, #0
7898    strneb  r2, [r2, r3, lsr #GC_CARD_SHIFT] @ mark card based on obj head
7899    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
7900    GOTO_OPCODE(ip)                     @ jump to next instruction
7901
7902/* ------------------------------ */
7903    .balign 64
7904.L_OP_INVOKE_VIRTUAL_QUICK: /* 0xf8 */
7905/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7906    /*
7907     * Handle an optimized virtual method call.
7908     *
7909     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7910     */
7911    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7912    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7913    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7914    FETCH(r1, 1)                        @ r1<- BBBB
7915    .if     (!0)
7916    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7917    .endif
7918    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7919    cmp     r2, #0                      @ is "this" null?
7920    beq     common_errNullObject        @ null "this", throw exception
7921    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7922    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7923    EXPORT_PC()                         @ invoke must export
7924    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7925    bl      common_invokeMethodNoRange @ continue on
7926
7927/* ------------------------------ */
7928    .balign 64
7929.L_OP_INVOKE_VIRTUAL_QUICK_RANGE: /* 0xf9 */
7930/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK_RANGE.S */
7931/* File: armv5te/OP_INVOKE_VIRTUAL_QUICK.S */
7932    /*
7933     * Handle an optimized virtual method call.
7934     *
7935     * for: [opt] invoke-virtual-quick, invoke-virtual-quick/range
7936     */
7937    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7938    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7939    FETCH(r3, 2)                        @ r3<- FEDC or CCCC
7940    FETCH(r1, 1)                        @ r1<- BBBB
7941    .if     (!1)
7942    and     r3, r3, #15                 @ r3<- C (or stays CCCC)
7943    .endif
7944    GET_VREG(r2, r3)                    @ r2<- vC ("this" ptr)
7945    cmp     r2, #0                      @ is "this" null?
7946    beq     common_errNullObject        @ null "this", throw exception
7947    ldr     r2, [r2, #offObject_clazz]  @ r2<- thisPtr->clazz
7948    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- thisPtr->clazz->vtable
7949    EXPORT_PC()                         @ invoke must export
7950    ldr     r0, [r2, r1, lsl #2]        @ r3<- vtable[BBBB]
7951    bl      common_invokeMethodRange @ continue on
7952
7953
7954/* ------------------------------ */
7955    .balign 64
7956.L_OP_INVOKE_SUPER_QUICK: /* 0xfa */
7957/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7958    /*
7959     * Handle an optimized "super" method call.
7960     *
7961     * for: [opt] invoke-super-quick, invoke-super-quick/range
7962     */
7963    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7964    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7965    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7966    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7967    .if     (!0)
7968    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7969    .endif
7970    FETCH(r1, 1)                        @ r1<- BBBB
7971    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
7972    EXPORT_PC()                         @ must export for invoke
7973    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
7974    GET_VREG(r3, r10)                   @ r3<- "this"
7975    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
7976    cmp     r3, #0                      @ null "this" ref?
7977    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
7978    beq     common_errNullObject        @ "this" is null, throw exception
7979    bl      common_invokeMethodNoRange @ continue on
7980
7981/* ------------------------------ */
7982    .balign 64
7983.L_OP_INVOKE_SUPER_QUICK_RANGE: /* 0xfb */
7984/* File: armv5te/OP_INVOKE_SUPER_QUICK_RANGE.S */
7985/* File: armv5te/OP_INVOKE_SUPER_QUICK.S */
7986    /*
7987     * Handle an optimized "super" method call.
7988     *
7989     * for: [opt] invoke-super-quick, invoke-super-quick/range
7990     */
7991    /* op vB, {vD, vE, vF, vG, vA}, class@CCCC */
7992    /* op vAA, {vCCCC..v(CCCC+AA-1)}, meth@BBBB */
7993    FETCH(r10, 2)                       @ r10<- GFED or CCCC
7994    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
7995    .if     (!1)
7996    and     r10, r10, #15               @ r10<- D (or stays CCCC)
7997    .endif
7998    FETCH(r1, 1)                        @ r1<- BBBB
7999    ldr     r2, [r2, #offMethod_clazz]  @ r2<- method->clazz
8000    EXPORT_PC()                         @ must export for invoke
8001    ldr     r2, [r2, #offClassObject_super]     @ r2<- method->clazz->super
8002    GET_VREG(r3, r10)                   @ r3<- "this"
8003    ldr     r2, [r2, #offClassObject_vtable]    @ r2<- ...clazz->super->vtable
8004    cmp     r3, #0                      @ null "this" ref?
8005    ldr     r0, [r2, r1, lsl #2]        @ r0<- super->vtable[BBBB]
8006    beq     common_errNullObject        @ "this" is null, throw exception
8007    bl      common_invokeMethodRange @ continue on
8008
8009
8010/* ------------------------------ */
8011    .balign 64
8012.L_OP_IPUT_OBJECT_VOLATILE: /* 0xfc */
8013/* File: armv5te/OP_IPUT_OBJECT_VOLATILE.S */
8014/* File: armv5te/OP_IPUT_OBJECT.S */
8015    /*
8016     * 32-bit instance field put.
8017     *
8018     * for: iput-object, iput-object-volatile
8019     */
8020    /* op vA, vB, field@CCCC */
8021    mov     r0, rINST, lsr #12          @ r0<- B
8022    ldr     r3, [rGLUE, #offGlue_methodClassDex]    @ r3<- DvmDex
8023    FETCH(r1, 1)                        @ r1<- field ref CCCC
8024    ldr     r2, [r3, #offDvmDex_pResFields] @ r2<- pDvmDex->pResFields
8025    GET_VREG(r9, r0)                    @ r9<- fp[B], the object pointer
8026    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved InstField ptr
8027    cmp     r0, #0                      @ is resolved entry null?
8028    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ no, already resolved
80298:  ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
8030    EXPORT_PC()                         @ resolve() could throw
8031    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
8032    bl      dvmResolveInstField         @ r0<- resolved InstField ptr
8033    cmp     r0, #0                      @ success?
8034    bne     .LOP_IPUT_OBJECT_VOLATILE_finish          @ yes, finish up
8035    b       common_exceptionThrown
8036
8037
8038/* ------------------------------ */
8039    .balign 64
8040.L_OP_SGET_OBJECT_VOLATILE: /* 0xfd */
8041/* File: armv5te/OP_SGET_OBJECT_VOLATILE.S */
8042/* File: armv5te/OP_SGET.S */
8043    /*
8044     * General 32-bit SGET handler.
8045     *
8046     * for: sget, sget-object, sget-boolean, sget-byte, sget-char, sget-short
8047     */
8048    /* op vAA, field@BBBB */
8049    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8050    FETCH(r1, 1)                        @ r1<- field ref BBBB
8051    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8052    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8053    cmp     r0, #0                      @ is resolved entry null?
8054    beq     .LOP_SGET_OBJECT_VOLATILE_resolve         @ yes, do resolve
8055.LOP_SGET_OBJECT_VOLATILE_finish: @ field ptr in r0
8056    ldr     r1, [r0, #offStaticField_value] @ r1<- field value
8057    SMP_DMB                            @ acquiring load
8058    mov     r2, rINST, lsr #8           @ r2<- AA
8059    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8060    SET_VREG(r1, r2)                    @ fp[AA]<- r1
8061    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8062    GOTO_OPCODE(ip)                     @ jump to next instruction
8063
8064
8065/* ------------------------------ */
8066    .balign 64
8067.L_OP_SPUT_OBJECT_VOLATILE: /* 0xfe */
8068/* File: armv5te/OP_SPUT_OBJECT_VOLATILE.S */
8069/* File: armv5te/OP_SPUT_OBJECT.S */
8070    /*
8071     * 32-bit SPUT handler for objects
8072     *
8073     * for: sput-object, sput-object-volatile
8074     */
8075    /* op vAA, field@BBBB */
8076    ldr     r2, [rGLUE, #offGlue_methodClassDex]    @ r2<- DvmDex
8077    FETCH(r1, 1)                        @ r1<- field ref BBBB
8078    ldr     r2, [r2, #offDvmDex_pResFields] @ r2<- dvmDex->pResFields
8079    ldr     r0, [r2, r1, lsl #2]        @ r0<- resolved StaticField ptr
8080    cmp     r0, #0                      @ is resolved entry null?
8081    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ no, continue
8082    ldr     r9, [rGLUE, #offGlue_method]    @ r9<- current method
8083    EXPORT_PC()                         @ resolve() could throw, so export now
8084    ldr     r0, [r9, #offMethod_clazz]  @ r0<- method->clazz
8085    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
8086    cmp     r0, #0                      @ success?
8087    bne     .LOP_SPUT_OBJECT_VOLATILE_finish          @ yes, finish
8088    b       common_exceptionThrown      @ no, handle exception
8089
8090
8091
8092/* ------------------------------ */
8093    .balign 64
8094.L_OP_UNUSED_FF: /* 0xff */
8095/* File: armv5te/OP_UNUSED_FF.S */
8096/* File: armv5te/unused.S */
8097    bl      common_abort
8098
8099
8100
8101    .balign 64
8102    .size   dvmAsmInstructionStart, .-dvmAsmInstructionStart
8103    .global dvmAsmInstructionEnd
8104dvmAsmInstructionEnd:
8105
8106/*
8107 * ===========================================================================
8108 *  Sister implementations
8109 * ===========================================================================
8110 */
8111    .global dvmAsmSisterStart
8112    .type   dvmAsmSisterStart, %function
8113    .text
8114    .balign 4
8115dvmAsmSisterStart:
8116
8117/* continuation for OP_CONST_STRING */
8118
8119    /*
8120     * Continuation if the String has not yet been resolved.
8121     *  r1: BBBB (String ref)
8122     *  r9: target register
8123     */
8124.LOP_CONST_STRING_resolve:
8125    EXPORT_PC()
8126    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8127    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8128    bl      dvmResolveString            @ r0<- String reference
8129    cmp     r0, #0                      @ failed?
8130    beq     common_exceptionThrown      @ yup, handle the exception
8131    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8132    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8133    SET_VREG(r0, r9)                    @ vAA<- r0
8134    GOTO_OPCODE(ip)                     @ jump to next instruction
8135
8136/* continuation for OP_CONST_STRING_JUMBO */
8137
8138    /*
8139     * Continuation if the String has not yet been resolved.
8140     *  r1: BBBBBBBB (String ref)
8141     *  r9: target register
8142     */
8143.LOP_CONST_STRING_JUMBO_resolve:
8144    EXPORT_PC()
8145    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8146    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8147    bl      dvmResolveString            @ r0<- String reference
8148    cmp     r0, #0                      @ failed?
8149    beq     common_exceptionThrown      @ yup, handle the exception
8150    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
8151    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8152    SET_VREG(r0, r9)                    @ vAA<- r0
8153    GOTO_OPCODE(ip)                     @ jump to next instruction
8154
8155/* continuation for OP_CONST_CLASS */
8156
8157    /*
8158     * Continuation if the Class has not yet been resolved.
8159     *  r1: BBBB (Class ref)
8160     *  r9: target register
8161     */
8162.LOP_CONST_CLASS_resolve:
8163    EXPORT_PC()
8164    ldr     r0, [rGLUE, #offGlue_method] @ r0<- glue->method
8165    mov     r2, #1                      @ r2<- true
8166    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8167    bl      dvmResolveClass             @ r0<- Class reference
8168    cmp     r0, #0                      @ failed?
8169    beq     common_exceptionThrown      @ yup, handle the exception
8170    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8171    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8172    SET_VREG(r0, r9)                    @ vAA<- r0
8173    GOTO_OPCODE(ip)                     @ jump to next instruction
8174
8175/* continuation for OP_CHECK_CAST */
8176
8177    /*
8178     * Trivial test failed, need to perform full check.  This is common.
8179     *  r0 holds obj->clazz
8180     *  r1 holds class resolved from BBBB
8181     *  r9 holds object
8182     */
8183.LOP_CHECK_CAST_fullcheck:
8184    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8185    cmp     r0, #0                      @ failed?
8186    bne     .LOP_CHECK_CAST_okay            @ no, success
8187
8188    @ A cast has failed.  We need to throw a ClassCastException with the
8189    @ class of the object that failed to be cast.
8190    EXPORT_PC()                         @ about to throw
8191    ldr     r3, [r9, #offObject_clazz]  @ r3<- obj->clazz
8192    ldr     r0, .LstrClassCastExceptionPtr
8193    ldr     r1, [r3, #offClassObject_descriptor] @ r1<- obj->clazz->descriptor
8194    bl      dvmThrowExceptionWithClassMessage
8195    b       common_exceptionThrown
8196
8197    /*
8198     * Resolution required.  This is the least-likely path.
8199     *
8200     *  r2 holds BBBB
8201     *  r9 holds object
8202     */
8203.LOP_CHECK_CAST_resolve:
8204    EXPORT_PC()                         @ resolve() could throw
8205    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8206    mov     r1, r2                      @ r1<- BBBB
8207    mov     r2, #0                      @ r2<- false
8208    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8209    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8210    cmp     r0, #0                      @ got null?
8211    beq     common_exceptionThrown      @ yes, handle exception
8212    mov     r1, r0                      @ r1<- class resolved from BBB
8213    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8214    b       .LOP_CHECK_CAST_resolved        @ pick up where we left off
8215
8216.LstrClassCastExceptionPtr:
8217    .word   .LstrClassCastException
8218
8219/* continuation for OP_INSTANCE_OF */
8220
8221    /*
8222     * Trivial test failed, need to perform full check.  This is common.
8223     *  r0 holds obj->clazz
8224     *  r1 holds class resolved from BBBB
8225     *  r9 holds A
8226     */
8227.LOP_INSTANCE_OF_fullcheck:
8228    bl      dvmInstanceofNonTrivial     @ r0<- boolean result
8229    @ fall through to OP_INSTANCE_OF_store
8230
8231    /*
8232     * r0 holds boolean result
8233     * r9 holds A
8234     */
8235.LOP_INSTANCE_OF_store:
8236    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8237    SET_VREG(r0, r9)                    @ vA<- r0
8238    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8239    GOTO_OPCODE(ip)                     @ jump to next instruction
8240
8241    /*
8242     * Trivial test succeeded, save and bail.
8243     *  r9 holds A
8244     */
8245.LOP_INSTANCE_OF_trivial:
8246    mov     r0, #1                      @ indicate success
8247    @ could b OP_INSTANCE_OF_store, but copying is faster and cheaper
8248    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8249    SET_VREG(r0, r9)                    @ vA<- r0
8250    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8251    GOTO_OPCODE(ip)                     @ jump to next instruction
8252
8253    /*
8254     * Resolution required.  This is the least-likely path.
8255     *
8256     *  r3 holds BBBB
8257     *  r9 holds A
8258     */
8259.LOP_INSTANCE_OF_resolve:
8260    EXPORT_PC()                         @ resolve() could throw
8261    ldr     r0, [rGLUE, #offGlue_method]    @ r0<- glue->method
8262    mov     r1, r3                      @ r1<- BBBB
8263    mov     r2, #1                      @ r2<- true
8264    ldr     r0, [r0, #offMethod_clazz]  @ r0<- method->clazz
8265    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8266    cmp     r0, #0                      @ got null?
8267    beq     common_exceptionThrown      @ yes, handle exception
8268    mov     r1, r0                      @ r1<- class resolved from BBB
8269    mov     r3, rINST, lsr #12          @ r3<- B
8270    GET_VREG(r0, r3)                    @ r0<- vB (object)
8271    ldr     r0, [r0, #offObject_clazz]  @ r0<- obj->clazz
8272    b       .LOP_INSTANCE_OF_resolved        @ pick up where we left off
8273
8274/* continuation for OP_NEW_INSTANCE */
8275
8276    .balign 32                          @ minimize cache lines
8277.LOP_NEW_INSTANCE_finish: @ r0=new object
8278    mov     r3, rINST, lsr #8           @ r3<- AA
8279    cmp     r0, #0                      @ failed?
8280    beq     common_exceptionThrown      @ yes, handle the exception
8281    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8282    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8283    SET_VREG(r0, r3)                    @ vAA<- r0
8284    GOTO_OPCODE(ip)                     @ jump to next instruction
8285
8286    /*
8287     * Class initialization required.
8288     *
8289     *  r0 holds class object
8290     */
8291.LOP_NEW_INSTANCE_needinit:
8292    mov     r9, r0                      @ save r0
8293    bl      dvmInitClass                @ initialize class
8294    cmp     r0, #0                      @ check boolean result
8295    mov     r0, r9                      @ restore r0
8296    bne     .LOP_NEW_INSTANCE_initialized     @ success, continue
8297    b       common_exceptionThrown      @ failed, deal with init exception
8298
8299    /*
8300     * Resolution required.  This is the least-likely path.
8301     *
8302     *  r1 holds BBBB
8303     */
8304.LOP_NEW_INSTANCE_resolve:
8305    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8306    mov     r2, #0                      @ r2<- false
8307    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8308    bl      dvmResolveClass             @ r0<- resolved ClassObject ptr
8309    cmp     r0, #0                      @ got null?
8310    bne     .LOP_NEW_INSTANCE_resolved        @ no, continue
8311    b       common_exceptionThrown      @ yes, handle exception
8312
8313.LstrInstantiationErrorPtr:
8314    .word   .LstrInstantiationError
8315
8316/* continuation for OP_NEW_ARRAY */
8317
8318
8319    /*
8320     * Resolve class.  (This is an uncommon case.)
8321     *
8322     *  r1 holds array length
8323     *  r2 holds class ref CCCC
8324     */
8325.LOP_NEW_ARRAY_resolve:
8326    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
8327    mov     r9, r1                      @ r9<- length (save)
8328    mov     r1, r2                      @ r1<- CCCC
8329    mov     r2, #0                      @ r2<- false
8330    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
8331    bl      dvmResolveClass             @ r0<- call(clazz, ref)
8332    cmp     r0, #0                      @ got null?
8333    mov     r1, r9                      @ r1<- length (restore)
8334    beq     common_exceptionThrown      @ yes, handle exception
8335    @ fall through to OP_NEW_ARRAY_finish
8336
8337    /*
8338     * Finish allocation.
8339     *
8340     *  r0 holds class
8341     *  r1 holds array length
8342     */
8343.LOP_NEW_ARRAY_finish:
8344    mov     r2, #ALLOC_DONT_TRACK       @ don't track in local refs table
8345    bl      dvmAllocArrayByClass        @ r0<- call(clazz, length, flags)
8346    cmp     r0, #0                      @ failed?
8347    mov     r2, rINST, lsr #8           @ r2<- A+
8348    beq     common_exceptionThrown      @ yes, handle the exception
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)                    @ vA<- r0
8353    GOTO_OPCODE(ip)                     @ jump to next instruction
8354
8355/* continuation for OP_FILLED_NEW_ARRAY */
8356
8357    /*
8358     * On entry:
8359     *  r0 holds array class
8360     *  r10 holds AA or BA
8361     */
8362.LOP_FILLED_NEW_ARRAY_continue:
8363    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8364    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8365    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8366    .if     0
8367    mov     r1, r10                     @ r1<- AA (length)
8368    .else
8369    mov     r1, r10, lsr #4             @ r1<- B (length)
8370    .endif
8371    cmp     rINST, #'I'                 @ array of ints?
8372    cmpne   rINST, #'L'                 @ array of objects?
8373    cmpne   rINST, #'['                 @ array of arrays?
8374    mov     r9, r1                      @ save length in r9
8375    bne     .LOP_FILLED_NEW_ARRAY_notimpl         @ no, not handled yet
8376    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8377    cmp     r0, #0                      @ null return?
8378    beq     common_exceptionThrown      @ alloc failed, handle exception
8379
8380    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8381    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8382    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8383    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8384    subs    r9, r9, #1                  @ length--, check for neg
8385    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8386    bmi     2f                          @ was zero, bail
8387
8388    @ copy values from registers into the array
8389    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8390    .if     0
8391    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
83921:  ldr     r3, [r2], #4                @ r3<- *r2++
8393    subs    r9, r9, #1                  @ count--
8394    str     r3, [r0], #4                @ *contents++ = vX
8395    bpl     1b
8396    @ continue at 2
8397    .else
8398    cmp     r9, #4                      @ length was initially 5?
8399    and     r2, r10, #15                @ r2<- A
8400    bne     1f                          @ <= 4 args, branch
8401    GET_VREG(r3, r2)                    @ r3<- vA
8402    sub     r9, r9, #1                  @ count--
8403    str     r3, [r0, #16]               @ contents[4] = vA
84041:  and     r2, r1, #15                 @ r2<- F/E/D/C
8405    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8406    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8407    subs    r9, r9, #1                  @ count--
8408    str     r3, [r0], #4                @ *contents++ = vX
8409    bpl     1b
8410    @ continue at 2
8411    .endif
8412
84132:
8414    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8415    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8416    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8417    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8418    cmp     r1, #'I'                         @ Is int array?
8419    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8420    GOTO_OPCODE(ip)                          @ execute it
8421
8422    /*
8423     * Throw an exception indicating that we have not implemented this
8424     * mode of filled-new-array.
8425     */
8426.LOP_FILLED_NEW_ARRAY_notimpl:
8427    ldr     r0, .L_strInternalError
8428    ldr     r1, .L_strFilledNewArrayNotImpl
8429    bl      dvmThrowException
8430    b       common_exceptionThrown
8431
8432    .if     (!0)                 @ define in one or the other, not both
8433.L_strFilledNewArrayNotImpl:
8434    .word   .LstrFilledNewArrayNotImpl
8435.L_strInternalError:
8436    .word   .LstrInternalError
8437    .endif
8438
8439/* continuation for OP_FILLED_NEW_ARRAY_RANGE */
8440
8441    /*
8442     * On entry:
8443     *  r0 holds array class
8444     *  r10 holds AA or BA
8445     */
8446.LOP_FILLED_NEW_ARRAY_RANGE_continue:
8447    ldr     r3, [r0, #offClassObject_descriptor] @ r3<- arrayClass->descriptor
8448    mov     r2, #ALLOC_DONT_TRACK       @ r2<- alloc flags
8449    ldrb    rINST, [r3, #1]             @ rINST<- descriptor[1]
8450    .if     1
8451    mov     r1, r10                     @ r1<- AA (length)
8452    .else
8453    mov     r1, r10, lsr #4             @ r1<- B (length)
8454    .endif
8455    cmp     rINST, #'I'                 @ array of ints?
8456    cmpne   rINST, #'L'                 @ array of objects?
8457    cmpne   rINST, #'['                 @ array of arrays?
8458    mov     r9, r1                      @ save length in r9
8459    bne     .LOP_FILLED_NEW_ARRAY_RANGE_notimpl         @ no, not handled yet
8460    bl      dvmAllocArrayByClass        @ r0<- call(arClass, length, flags)
8461    cmp     r0, #0                      @ null return?
8462    beq     common_exceptionThrown      @ alloc failed, handle exception
8463
8464    FETCH(r1, 2)                        @ r1<- FEDC or CCCC
8465    str     r0, [rGLUE, #offGlue_retval]      @ retval.l <- new array
8466    str     rINST, [rGLUE, #offGlue_retval+4] @ retval.h <- type
8467    add     r0, r0, #offArrayObject_contents @ r0<- newArray->contents
8468    subs    r9, r9, #1                  @ length--, check for neg
8469    FETCH_ADVANCE_INST(3)               @ advance to next instr, load rINST
8470    bmi     2f                          @ was zero, bail
8471
8472    @ copy values from registers into the array
8473    @ r0=array, r1=CCCC/FEDC, r9=length (from AA or B), r10=AA/BA
8474    .if     1
8475    add     r2, rFP, r1, lsl #2         @ r2<- &fp[CCCC]
84761:  ldr     r3, [r2], #4                @ r3<- *r2++
8477    subs    r9, r9, #1                  @ count--
8478    str     r3, [r0], #4                @ *contents++ = vX
8479    bpl     1b
8480    @ continue at 2
8481    .else
8482    cmp     r9, #4                      @ length was initially 5?
8483    and     r2, r10, #15                @ r2<- A
8484    bne     1f                          @ <= 4 args, branch
8485    GET_VREG(r3, r2)                    @ r3<- vA
8486    sub     r9, r9, #1                  @ count--
8487    str     r3, [r0, #16]               @ contents[4] = vA
84881:  and     r2, r1, #15                 @ r2<- F/E/D/C
8489    GET_VREG(r3, r2)                    @ r3<- vF/vE/vD/vC
8490    mov     r1, r1, lsr #4              @ r1<- next reg in low 4
8491    subs    r9, r9, #1                  @ count--
8492    str     r3, [r0], #4                @ *contents++ = vX
8493    bpl     1b
8494    @ continue at 2
8495    .endif
8496
84972:
8498    ldr     r0, [rGLUE, #offGlue_retval]     @ r0<- object
8499    ldr     r1, [rGLUE, #offGlue_retval+4]   @ r1<- type
8500    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8501    GET_INST_OPCODE(ip)                      @ ip<- opcode from rINST
8502    cmp     r1, #'I'                         @ Is int array?
8503    strneb  r2, [r2, r0, lsr #GC_CARD_SHIFT] @ Mark card based on object head
8504    GOTO_OPCODE(ip)                          @ execute it
8505
8506    /*
8507     * Throw an exception indicating that we have not implemented this
8508     * mode of filled-new-array.
8509     */
8510.LOP_FILLED_NEW_ARRAY_RANGE_notimpl:
8511    ldr     r0, .L_strInternalError
8512    ldr     r1, .L_strFilledNewArrayNotImpl
8513    bl      dvmThrowException
8514    b       common_exceptionThrown
8515
8516    .if     (!1)                 @ define in one or the other, not both
8517.L_strFilledNewArrayNotImpl:
8518    .word   .LstrFilledNewArrayNotImpl
8519.L_strInternalError:
8520    .word   .LstrInternalError
8521    .endif
8522
8523/* continuation for OP_CMPL_FLOAT */
8524
8525    @ Test for NaN with a second comparison.  EABI forbids testing bit
8526    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8527    @ make the library call.
8528.LOP_CMPL_FLOAT_gt_or_nan:
8529    mov     r1, r9                      @ reverse order
8530    mov     r0, r10
8531    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8532    @bleq    common_abort
8533    movcc   r1, #1                      @ (greater than) r1<- 1
8534    bcc     .LOP_CMPL_FLOAT_finish
8535    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8536    b       .LOP_CMPL_FLOAT_finish
8537
8538
8539#if 0       /* "clasic" form */
8540    FETCH(r0, 1)                        @ r0<- CCBB
8541    and     r2, r0, #255                @ r2<- BB
8542    mov     r3, r0, lsr #8              @ r3<- CC
8543    GET_VREG(r9, r2)                    @ r9<- vBB
8544    GET_VREG(r10, r3)                   @ r10<- vCC
8545    mov     r0, r9                      @ r0<- vBB
8546    mov     r1, r10                     @ r1<- vCC
8547    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8548    cmp     r0, #0                      @ equal?
8549    movne   r1, #0                      @ yes, result is 0
8550    bne     OP_CMPL_FLOAT_finish
8551    mov     r0, r9                      @ r0<- vBB
8552    mov     r1, r10                     @ r1<- vCC
8553    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8554    cmp     r0, #0                      @ less than?
8555    b       OP_CMPL_FLOAT_continue
8556@%break
8557
8558OP_CMPL_FLOAT_continue:
8559    mvnne   r1, #0                      @ yes, result is -1
8560    bne     OP_CMPL_FLOAT_finish
8561    mov     r0, r9                      @ r0<- vBB
8562    mov     r1, r10                     @ r1<- vCC
8563    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8564    cmp     r0, #0                      @ greater than?
8565    beq     OP_CMPL_FLOAT_nan               @ no, must be NaN
8566    mov     r1, #1                      @ yes, result is 1
8567    @ fall through to _finish
8568
8569OP_CMPL_FLOAT_finish:
8570    mov     r3, rINST, lsr #8           @ r3<- AA
8571    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8572    SET_VREG(r1, r3)                    @ vAA<- r1
8573    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8574    GOTO_OPCODE(ip)                     @ jump to next instruction
8575
8576    /*
8577     * This is expected to be uncommon, so we double-branch (once to here,
8578     * again back to _finish).
8579     */
8580OP_CMPL_FLOAT_nan:
8581    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8582    b       OP_CMPL_FLOAT_finish
8583
8584#endif
8585
8586/* continuation for OP_CMPG_FLOAT */
8587
8588    @ Test for NaN with a second comparison.  EABI forbids testing bit
8589    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8590    @ make the library call.
8591.LOP_CMPG_FLOAT_gt_or_nan:
8592    mov     r1, r9                      @ reverse order
8593    mov     r0, r10
8594    bl      __aeabi_cfcmple             @ r0<- Z set if eq, C clear if <
8595    @bleq    common_abort
8596    movcc   r1, #1                      @ (greater than) r1<- 1
8597    bcc     .LOP_CMPG_FLOAT_finish
8598    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8599    b       .LOP_CMPG_FLOAT_finish
8600
8601
8602#if 0       /* "clasic" form */
8603    FETCH(r0, 1)                        @ r0<- CCBB
8604    and     r2, r0, #255                @ r2<- BB
8605    mov     r3, r0, lsr #8              @ r3<- CC
8606    GET_VREG(r9, r2)                    @ r9<- vBB
8607    GET_VREG(r10, r3)                   @ r10<- vCC
8608    mov     r0, r9                      @ r0<- vBB
8609    mov     r1, r10                     @ r1<- vCC
8610    bl      __aeabi_fcmpeq              @ r0<- (vBB == vCC)
8611    cmp     r0, #0                      @ equal?
8612    movne   r1, #0                      @ yes, result is 0
8613    bne     OP_CMPG_FLOAT_finish
8614    mov     r0, r9                      @ r0<- vBB
8615    mov     r1, r10                     @ r1<- vCC
8616    bl      __aeabi_fcmplt              @ r0<- (vBB < vCC)
8617    cmp     r0, #0                      @ less than?
8618    b       OP_CMPG_FLOAT_continue
8619@%break
8620
8621OP_CMPG_FLOAT_continue:
8622    mvnne   r1, #0                      @ yes, result is -1
8623    bne     OP_CMPG_FLOAT_finish
8624    mov     r0, r9                      @ r0<- vBB
8625    mov     r1, r10                     @ r1<- vCC
8626    bl      __aeabi_fcmpgt              @ r0<- (vBB > vCC)
8627    cmp     r0, #0                      @ greater than?
8628    beq     OP_CMPG_FLOAT_nan               @ no, must be NaN
8629    mov     r1, #1                      @ yes, result is 1
8630    @ fall through to _finish
8631
8632OP_CMPG_FLOAT_finish:
8633    mov     r3, rINST, lsr #8           @ r3<- AA
8634    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8635    SET_VREG(r1, r3)                    @ vAA<- r1
8636    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8637    GOTO_OPCODE(ip)                     @ jump to next instruction
8638
8639    /*
8640     * This is expected to be uncommon, so we double-branch (once to here,
8641     * again back to _finish).
8642     */
8643OP_CMPG_FLOAT_nan:
8644    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8645    b       OP_CMPG_FLOAT_finish
8646
8647#endif
8648
8649/* continuation for OP_CMPL_DOUBLE */
8650
8651    @ Test for NaN with a second comparison.  EABI forbids testing bit
8652    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8653    @ make the library call.
8654.LOP_CMPL_DOUBLE_gt_or_nan:
8655    ldmia   r10, {r0-r1}                @ reverse order
8656    ldmia   r9, {r2-r3}
8657    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8658    @bleq    common_abort
8659    movcc   r1, #1                      @ (greater than) r1<- 1
8660    bcc     .LOP_CMPL_DOUBLE_finish
8661    mvn     r1, #0                            @ r1<- 1 or -1 for NaN
8662    b       .LOP_CMPL_DOUBLE_finish
8663
8664/* continuation for OP_CMPG_DOUBLE */
8665
8666    @ Test for NaN with a second comparison.  EABI forbids testing bit
8667    @ patterns, and we can't represent 0x7fc00000 in immediate form, so
8668    @ make the library call.
8669.LOP_CMPG_DOUBLE_gt_or_nan:
8670    ldmia   r10, {r0-r1}                @ reverse order
8671    ldmia   r9, {r2-r3}
8672    bl      __aeabi_cdcmple             @ r0<- Z set if eq, C clear if <
8673    @bleq    common_abort
8674    movcc   r1, #1                      @ (greater than) r1<- 1
8675    bcc     .LOP_CMPG_DOUBLE_finish
8676    mov     r1, #1                            @ r1<- 1 or -1 for NaN
8677    b       .LOP_CMPG_DOUBLE_finish
8678
8679/* continuation for OP_CMP_LONG */
8680
8681.LOP_CMP_LONG_less:
8682    mvn     r1, #0                      @ r1<- -1
8683    @ Want to cond code the next mov so we can avoid branch, but don't see it;
8684    @ instead, we just replicate the tail end.
8685    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8686    SET_VREG(r1, r9)                    @ vAA<- r1
8687    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8688    GOTO_OPCODE(ip)                     @ jump to next instruction
8689
8690.LOP_CMP_LONG_greater:
8691    mov     r1, #1                      @ r1<- 1
8692    @ fall through to _finish
8693
8694.LOP_CMP_LONG_finish:
8695    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8696    SET_VREG(r1, r9)                    @ vAA<- r1
8697    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8698    GOTO_OPCODE(ip)                     @ jump to next instruction
8699
8700/* continuation for OP_AGET_WIDE */
8701
8702.LOP_AGET_WIDE_finish:
8703    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8704    add     r0, r0, #offArrayObject_contents
8705    ldmia   r0, {r2-r3}                 @ r2/r3 <- vBB[vCC]
8706    add     r9, rFP, r9, lsl #2         @ r9<- &fp[AA]
8707    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8708    stmia   r9, {r2-r3}                 @ vAA/vAA+1<- r2/r3
8709    GOTO_OPCODE(ip)                     @ jump to next instruction
8710
8711/* continuation for OP_APUT_WIDE */
8712
8713.LOP_APUT_WIDE_finish:
8714    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8715    ldmia   r9, {r2-r3}                 @ r2/r3<- vAA/vAA+1
8716    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8717    add     r0, #offArrayObject_contents
8718    stmia   r0, {r2-r3}                 @ vBB[vCC] <- r2/r3
8719    GOTO_OPCODE(ip)                     @ jump to next instruction
8720
8721/* continuation for OP_APUT_OBJECT */
8722    /*
8723     * On entry:
8724     *  rINST = vBB (arrayObj)
8725     *  r9 = vAA (obj)
8726     *  r10 = offset into array (vBB + vCC * width)
8727     */
8728.LOP_APUT_OBJECT_finish:
8729    cmp     r9, #0                      @ storing null reference?
8730    beq     .LOP_APUT_OBJECT_skip_check      @ yes, skip type checks
8731    ldr     r0, [r9, #offObject_clazz]  @ r0<- obj->clazz
8732    ldr     r1, [rINST, #offObject_clazz]  @ r1<- arrayObj->clazz
8733    bl      dvmCanPutArrayElement       @ test object type vs. array type
8734    cmp     r0, #0                      @ okay?
8735    beq     common_errArrayStore        @ no
8736    mov     r1, rINST                   @ r1<- arrayObj
8737    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8738    ldr     r2, [rGLUE, #offGlue_cardTable]     @ get biased CT base
8739    add     r10, #offArrayObject_contents   @ r0<- pointer to slot
8740    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8741    str     r9, [r10]                   @ vBB[vCC]<- vAA
8742    strb    r2, [r2, r1, lsr #GC_CARD_SHIFT] @ mark card using object head
8743    GOTO_OPCODE(ip)                     @ jump to next instruction
8744.LOP_APUT_OBJECT_skip_check:
8745    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8746    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8747    str     r9, [r10, #offArrayObject_contents] @ vBB[vCC]<- vAA
8748    GOTO_OPCODE(ip)                     @ jump to next instruction
8749
8750/* continuation for OP_IGET */
8751
8752    /*
8753     * Currently:
8754     *  r0 holds resolved field
8755     *  r9 holds object
8756     */
8757.LOP_IGET_finish:
8758    @bl      common_squeak0
8759    cmp     r9, #0                      @ check object for null
8760    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8761    beq     common_errNullObject        @ object was null
8762    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8763    @ no-op                             @ acquiring load
8764    mov     r2, rINST, lsr #8           @ r2<- A+
8765    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8766    and     r2, r2, #15                 @ r2<- A
8767    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8768    SET_VREG(r0, r2)                    @ fp[A]<- r0
8769    GOTO_OPCODE(ip)                     @ jump to next instruction
8770
8771/* continuation for OP_IGET_WIDE */
8772
8773    /*
8774     * Currently:
8775     *  r0 holds resolved field
8776     *  r9 holds object
8777     */
8778.LOP_IGET_WIDE_finish:
8779    cmp     r9, #0                      @ check object for null
8780    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8781    beq     common_errNullObject        @ object was null
8782    .if 0
8783    add     r0, r9, r3                  @ r0<- address of field
8784    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
8785    .else
8786    add     r9, r9, r3                  @ r9<- obj + field offset
8787    ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
8788    .endif
8789    mov     r2, rINST, lsr #8           @ r2<- A+
8790    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8791    and     r2, r2, #15                 @ r2<- A
8792    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
8793    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8794    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
8795    GOTO_OPCODE(ip)                     @ jump to next instruction
8796
8797/* continuation for OP_IGET_OBJECT */
8798
8799    /*
8800     * Currently:
8801     *  r0 holds resolved field
8802     *  r9 holds object
8803     */
8804.LOP_IGET_OBJECT_finish:
8805    @bl      common_squeak0
8806    cmp     r9, #0                      @ check object for null
8807    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8808    beq     common_errNullObject        @ object was null
8809    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8810    @ no-op                             @ acquiring load
8811    mov     r2, rINST, lsr #8           @ r2<- A+
8812    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8813    and     r2, r2, #15                 @ r2<- A
8814    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8815    SET_VREG(r0, r2)                    @ fp[A]<- r0
8816    GOTO_OPCODE(ip)                     @ jump to next instruction
8817
8818/* continuation for OP_IGET_BOOLEAN */
8819
8820    /*
8821     * Currently:
8822     *  r0 holds resolved field
8823     *  r9 holds object
8824     */
8825.LOP_IGET_BOOLEAN_finish:
8826    @bl      common_squeak1
8827    cmp     r9, #0                      @ check object for null
8828    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8829    beq     common_errNullObject        @ object was null
8830    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8831    @ no-op                             @ acquiring load
8832    mov     r2, rINST, lsr #8           @ r2<- A+
8833    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8834    and     r2, r2, #15                 @ r2<- A
8835    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8836    SET_VREG(r0, r2)                    @ fp[A]<- r0
8837    GOTO_OPCODE(ip)                     @ jump to next instruction
8838
8839/* continuation for OP_IGET_BYTE */
8840
8841    /*
8842     * Currently:
8843     *  r0 holds resolved field
8844     *  r9 holds object
8845     */
8846.LOP_IGET_BYTE_finish:
8847    @bl      common_squeak2
8848    cmp     r9, #0                      @ check object for null
8849    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8850    beq     common_errNullObject        @ object was null
8851    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8852    @ no-op                             @ acquiring load
8853    mov     r2, rINST, lsr #8           @ r2<- A+
8854    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8855    and     r2, r2, #15                 @ r2<- A
8856    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8857    SET_VREG(r0, r2)                    @ fp[A]<- r0
8858    GOTO_OPCODE(ip)                     @ jump to next instruction
8859
8860/* continuation for OP_IGET_CHAR */
8861
8862    /*
8863     * Currently:
8864     *  r0 holds resolved field
8865     *  r9 holds object
8866     */
8867.LOP_IGET_CHAR_finish:
8868    @bl      common_squeak3
8869    cmp     r9, #0                      @ check object for null
8870    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8871    beq     common_errNullObject        @ object was null
8872    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8873    @ no-op                             @ acquiring load
8874    mov     r2, rINST, lsr #8           @ r2<- A+
8875    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8876    and     r2, r2, #15                 @ r2<- A
8877    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8878    SET_VREG(r0, r2)                    @ fp[A]<- r0
8879    GOTO_OPCODE(ip)                     @ jump to next instruction
8880
8881/* continuation for OP_IGET_SHORT */
8882
8883    /*
8884     * Currently:
8885     *  r0 holds resolved field
8886     *  r9 holds object
8887     */
8888.LOP_IGET_SHORT_finish:
8889    @bl      common_squeak4
8890    cmp     r9, #0                      @ check object for null
8891    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8892    beq     common_errNullObject        @ object was null
8893    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
8894    @ no-op                             @ acquiring load
8895    mov     r2, rINST, lsr #8           @ r2<- A+
8896    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8897    and     r2, r2, #15                 @ r2<- A
8898    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8899    SET_VREG(r0, r2)                    @ fp[A]<- r0
8900    GOTO_OPCODE(ip)                     @ jump to next instruction
8901
8902/* continuation for OP_IPUT */
8903
8904    /*
8905     * Currently:
8906     *  r0 holds resolved field
8907     *  r9 holds object
8908     */
8909.LOP_IPUT_finish:
8910    @bl      common_squeak0
8911    mov     r1, rINST, lsr #8           @ r1<- A+
8912    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8913    and     r1, r1, #15                 @ r1<- A
8914    cmp     r9, #0                      @ check object for null
8915    GET_VREG(r0, r1)                    @ r0<- fp[A]
8916    beq     common_errNullObject        @ object was null
8917    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8918    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8919    @ no-op                             @ releasing store
8920    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8921    GOTO_OPCODE(ip)                     @ jump to next instruction
8922
8923/* continuation for OP_IPUT_WIDE */
8924
8925    /*
8926     * Currently:
8927     *  r0 holds resolved field
8928     *  r9 holds object
8929     */
8930.LOP_IPUT_WIDE_finish:
8931    mov     r2, rINST, lsr #8           @ r2<- A+
8932    cmp     r9, #0                      @ check object for null
8933    and     r2, r2, #15                 @ r2<- A
8934    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8935    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
8936    beq     common_errNullObject        @ object was null
8937    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8938    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
8939    GET_INST_OPCODE(r10)                @ extract opcode from rINST
8940    add     r2, r9, r3                  @ r2<- object + byte offset
8941    .if 0
8942    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
8943    .else
8944    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
8945    .endif
8946    GOTO_OPCODE(r10)                    @ jump to next instruction
8947
8948/* continuation for OP_IPUT_OBJECT */
8949
8950    /*
8951     * Currently:
8952     *  r0 holds resolved field
8953     *  r9 holds object
8954     */
8955.LOP_IPUT_OBJECT_finish:
8956    @bl      common_squeak0
8957    mov     r1, rINST, lsr #8           @ r1<- A+
8958    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8959    and     r1, r1, #15                 @ r1<- A
8960    cmp     r9, #0                      @ check object for null
8961    GET_VREG(r0, r1)                    @ r0<- fp[A]
8962    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
8963    beq     common_errNullObject        @ object was null
8964    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8965    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8966    @ no-op                             @ releasing store
8967    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
8968    cmp     r0, #0                      @ stored a null reference?
8969    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
8970    GOTO_OPCODE(ip)                     @ jump to next instruction
8971
8972/* continuation for OP_IPUT_BOOLEAN */
8973
8974    /*
8975     * Currently:
8976     *  r0 holds resolved field
8977     *  r9 holds object
8978     */
8979.LOP_IPUT_BOOLEAN_finish:
8980    @bl      common_squeak1
8981    mov     r1, rINST, lsr #8           @ r1<- A+
8982    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
8983    and     r1, r1, #15                 @ r1<- A
8984    cmp     r9, #0                      @ check object for null
8985    GET_VREG(r0, r1)                    @ r0<- fp[A]
8986    beq     common_errNullObject        @ object was null
8987    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
8988    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
8989    @ no-op                             @ releasing store
8990    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
8991    GOTO_OPCODE(ip)                     @ jump to next instruction
8992
8993/* continuation for OP_IPUT_BYTE */
8994
8995    /*
8996     * Currently:
8997     *  r0 holds resolved field
8998     *  r9 holds object
8999     */
9000.LOP_IPUT_BYTE_finish:
9001    @bl      common_squeak2
9002    mov     r1, rINST, lsr #8           @ r1<- A+
9003    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9004    and     r1, r1, #15                 @ r1<- A
9005    cmp     r9, #0                      @ check object for null
9006    GET_VREG(r0, r1)                    @ r0<- fp[A]
9007    beq     common_errNullObject        @ object was null
9008    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9009    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9010    @ no-op                             @ releasing store
9011    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9012    GOTO_OPCODE(ip)                     @ jump to next instruction
9013
9014/* continuation for OP_IPUT_CHAR */
9015
9016    /*
9017     * Currently:
9018     *  r0 holds resolved field
9019     *  r9 holds object
9020     */
9021.LOP_IPUT_CHAR_finish:
9022    @bl      common_squeak3
9023    mov     r1, rINST, lsr #8           @ r1<- A+
9024    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9025    and     r1, r1, #15                 @ r1<- A
9026    cmp     r9, #0                      @ check object for null
9027    GET_VREG(r0, r1)                    @ r0<- fp[A]
9028    beq     common_errNullObject        @ object was null
9029    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9030    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9031    @ no-op                             @ releasing store
9032    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9033    GOTO_OPCODE(ip)                     @ jump to next instruction
9034
9035/* continuation for OP_IPUT_SHORT */
9036
9037    /*
9038     * Currently:
9039     *  r0 holds resolved field
9040     *  r9 holds object
9041     */
9042.LOP_IPUT_SHORT_finish:
9043    @bl      common_squeak4
9044    mov     r1, rINST, lsr #8           @ r1<- A+
9045    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9046    and     r1, r1, #15                 @ r1<- A
9047    cmp     r9, #0                      @ check object for null
9048    GET_VREG(r0, r1)                    @ r0<- fp[A]
9049    beq     common_errNullObject        @ object was null
9050    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9051    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9052    @ no-op                             @ releasing store
9053    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9054    GOTO_OPCODE(ip)                     @ jump to next instruction
9055
9056/* continuation for OP_SGET */
9057
9058    /*
9059     * Continuation if the field has not yet been resolved.
9060     *  r1: BBBB field ref
9061     */
9062.LOP_SGET_resolve:
9063    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9064    EXPORT_PC()                         @ resolve() could throw, so export now
9065    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9066    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9067    cmp     r0, #0                      @ success?
9068    bne     .LOP_SGET_finish          @ yes, finish
9069    b       common_exceptionThrown      @ no, handle exception
9070
9071/* continuation for OP_SGET_WIDE */
9072
9073    /*
9074     * Continuation if the field has not yet been resolved.
9075     *  r1: BBBB field ref
9076     *
9077     * Returns StaticField pointer in r0.
9078     */
9079.LOP_SGET_WIDE_resolve:
9080    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9081    EXPORT_PC()                         @ resolve() could throw, so export now
9082    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9083    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9084    cmp     r0, #0                      @ success?
9085    bne     .LOP_SGET_WIDE_finish          @ yes, finish
9086    b       common_exceptionThrown      @ no, handle exception
9087
9088/* continuation for OP_SGET_OBJECT */
9089
9090    /*
9091     * Continuation if the field has not yet been resolved.
9092     *  r1: BBBB field ref
9093     */
9094.LOP_SGET_OBJECT_resolve:
9095    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9096    EXPORT_PC()                         @ resolve() could throw, so export now
9097    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9098    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9099    cmp     r0, #0                      @ success?
9100    bne     .LOP_SGET_OBJECT_finish          @ yes, finish
9101    b       common_exceptionThrown      @ no, handle exception
9102
9103/* continuation for OP_SGET_BOOLEAN */
9104
9105    /*
9106     * Continuation if the field has not yet been resolved.
9107     *  r1: BBBB field ref
9108     */
9109.LOP_SGET_BOOLEAN_resolve:
9110    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9111    EXPORT_PC()                         @ resolve() could throw, so export now
9112    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9113    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9114    cmp     r0, #0                      @ success?
9115    bne     .LOP_SGET_BOOLEAN_finish          @ yes, finish
9116    b       common_exceptionThrown      @ no, handle exception
9117
9118/* continuation for OP_SGET_BYTE */
9119
9120    /*
9121     * Continuation if the field has not yet been resolved.
9122     *  r1: BBBB field ref
9123     */
9124.LOP_SGET_BYTE_resolve:
9125    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9126    EXPORT_PC()                         @ resolve() could throw, so export now
9127    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9128    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9129    cmp     r0, #0                      @ success?
9130    bne     .LOP_SGET_BYTE_finish          @ yes, finish
9131    b       common_exceptionThrown      @ no, handle exception
9132
9133/* continuation for OP_SGET_CHAR */
9134
9135    /*
9136     * Continuation if the field has not yet been resolved.
9137     *  r1: BBBB field ref
9138     */
9139.LOP_SGET_CHAR_resolve:
9140    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9141    EXPORT_PC()                         @ resolve() could throw, so export now
9142    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9143    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9144    cmp     r0, #0                      @ success?
9145    bne     .LOP_SGET_CHAR_finish          @ yes, finish
9146    b       common_exceptionThrown      @ no, handle exception
9147
9148/* continuation for OP_SGET_SHORT */
9149
9150    /*
9151     * Continuation if the field has not yet been resolved.
9152     *  r1: BBBB field ref
9153     */
9154.LOP_SGET_SHORT_resolve:
9155    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9156    EXPORT_PC()                         @ resolve() could throw, so export now
9157    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9158    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9159    cmp     r0, #0                      @ success?
9160    bne     .LOP_SGET_SHORT_finish          @ yes, finish
9161    b       common_exceptionThrown      @ no, handle exception
9162
9163/* continuation for OP_SPUT */
9164
9165    /*
9166     * Continuation if the field has not yet been resolved.
9167     *  r1: BBBB field ref
9168     */
9169.LOP_SPUT_resolve:
9170    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9171    EXPORT_PC()                         @ resolve() could throw, so export now
9172    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9173    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9174    cmp     r0, #0                      @ success?
9175    bne     .LOP_SPUT_finish          @ yes, finish
9176    b       common_exceptionThrown      @ no, handle exception
9177
9178/* continuation for OP_SPUT_WIDE */
9179
9180    /*
9181     * Continuation if the field has not yet been resolved.
9182     *  r1: BBBB field ref
9183     *  r9: &fp[AA]
9184     *
9185     * Returns StaticField pointer in r2.
9186     */
9187.LOP_SPUT_WIDE_resolve:
9188    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9189    EXPORT_PC()                         @ resolve() could throw, so export now
9190    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9191    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9192    cmp     r0, #0                      @ success?
9193    mov     r2, r0                      @ copy to r2
9194    bne     .LOP_SPUT_WIDE_finish          @ yes, finish
9195    b       common_exceptionThrown      @ no, handle exception
9196
9197/* continuation for OP_SPUT_OBJECT */
9198.LOP_SPUT_OBJECT_finish:   @ field ptr in r0
9199    mov     r2, rINST, lsr #8           @ r2<- AA
9200    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9201    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9202    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9203    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9204    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9205    @ no-op                             @ releasing store
9206    str     r1, [r0, #offStaticField_value]  @ field<- vAA
9207    cmp     r1, #0                      @ stored a null object?
9208    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9209    GOTO_OPCODE(ip)                     @ jump to next instruction
9210
9211/* continuation for OP_SPUT_BOOLEAN */
9212
9213    /*
9214     * Continuation if the field has not yet been resolved.
9215     *  r1: BBBB field ref
9216     */
9217.LOP_SPUT_BOOLEAN_resolve:
9218    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9219    EXPORT_PC()                         @ resolve() could throw, so export now
9220    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9221    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9222    cmp     r0, #0                      @ success?
9223    bne     .LOP_SPUT_BOOLEAN_finish          @ yes, finish
9224    b       common_exceptionThrown      @ no, handle exception
9225
9226/* continuation for OP_SPUT_BYTE */
9227
9228    /*
9229     * Continuation if the field has not yet been resolved.
9230     *  r1: BBBB field ref
9231     */
9232.LOP_SPUT_BYTE_resolve:
9233    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9234    EXPORT_PC()                         @ resolve() could throw, so export now
9235    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9236    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9237    cmp     r0, #0                      @ success?
9238    bne     .LOP_SPUT_BYTE_finish          @ yes, finish
9239    b       common_exceptionThrown      @ no, handle exception
9240
9241/* continuation for OP_SPUT_CHAR */
9242
9243    /*
9244     * Continuation if the field has not yet been resolved.
9245     *  r1: BBBB field ref
9246     */
9247.LOP_SPUT_CHAR_resolve:
9248    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9249    EXPORT_PC()                         @ resolve() could throw, so export now
9250    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9251    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9252    cmp     r0, #0                      @ success?
9253    bne     .LOP_SPUT_CHAR_finish          @ yes, finish
9254    b       common_exceptionThrown      @ no, handle exception
9255
9256/* continuation for OP_SPUT_SHORT */
9257
9258    /*
9259     * Continuation if the field has not yet been resolved.
9260     *  r1: BBBB field ref
9261     */
9262.LOP_SPUT_SHORT_resolve:
9263    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9264    EXPORT_PC()                         @ resolve() could throw, so export now
9265    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9266    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9267    cmp     r0, #0                      @ success?
9268    bne     .LOP_SPUT_SHORT_finish          @ yes, finish
9269    b       common_exceptionThrown      @ no, handle exception
9270
9271/* continuation for OP_INVOKE_VIRTUAL */
9272
9273    /*
9274     * At this point:
9275     *  r0 = resolved base method
9276     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9277     */
9278.LOP_INVOKE_VIRTUAL_continue:
9279    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9280    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9281    cmp     r1, #0                      @ is "this" null?
9282    beq     common_errNullObject        @ null "this", throw exception
9283    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9284    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9285    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9286    bl      common_invokeMethodNoRange @ continue on
9287
9288/* continuation for OP_INVOKE_SUPER */
9289
9290    /*
9291     * At this point:
9292     *  r0 = resolved base method
9293     *  r9 = method->clazz
9294     */
9295.LOP_INVOKE_SUPER_continue:
9296    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9297    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9298    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9299    EXPORT_PC()                         @ must export for invoke
9300    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9301    bcs     .LOP_INVOKE_SUPER_nsm             @ method not present in superclass
9302    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9303    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9304    bl      common_invokeMethodNoRange @ continue on
9305
9306.LOP_INVOKE_SUPER_resolve:
9307    mov     r0, r9                      @ r0<- method->clazz
9308    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9309    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9310    cmp     r0, #0                      @ got null?
9311    bne     .LOP_INVOKE_SUPER_continue        @ no, continue
9312    b       common_exceptionThrown      @ yes, handle exception
9313
9314    /*
9315     * Throw a NoSuchMethodError with the method name as the message.
9316     *  r0 = resolved base method
9317     */
9318.LOP_INVOKE_SUPER_nsm:
9319    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9320    b       common_errNoSuchMethod
9321
9322/* continuation for OP_INVOKE_DIRECT */
9323
9324    /*
9325     * On entry:
9326     *  r1 = reference (BBBB or CCCC)
9327     *  r10 = "this" register
9328     */
9329.LOP_INVOKE_DIRECT_resolve:
9330    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9331    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9332    mov     r2, #METHOD_DIRECT          @ resolver method type
9333    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9334    cmp     r0, #0                      @ got null?
9335    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9336    bne     .LOP_INVOKE_DIRECT_finish          @ no, continue
9337    b       common_exceptionThrown      @ yes, handle exception
9338
9339/* continuation for OP_INVOKE_VIRTUAL_RANGE */
9340
9341    /*
9342     * At this point:
9343     *  r0 = resolved base method
9344     *  r10 = C or CCCC (index of first arg, which is the "this" ptr)
9345     */
9346.LOP_INVOKE_VIRTUAL_RANGE_continue:
9347    GET_VREG(r1, r10)                   @ r1<- "this" ptr
9348    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9349    cmp     r1, #0                      @ is "this" null?
9350    beq     common_errNullObject        @ null "this", throw exception
9351    ldr     r3, [r1, #offObject_clazz]  @ r1<- thisPtr->clazz
9352    ldr     r3, [r3, #offClassObject_vtable]    @ r3<- thisPtr->clazz->vtable
9353    ldr     r0, [r3, r2, lsl #2]        @ r3<- vtable[methodIndex]
9354    bl      common_invokeMethodRange @ continue on
9355
9356/* continuation for OP_INVOKE_SUPER_RANGE */
9357
9358    /*
9359     * At this point:
9360     *  r0 = resolved base method
9361     *  r9 = method->clazz
9362     */
9363.LOP_INVOKE_SUPER_RANGE_continue:
9364    ldr     r1, [r9, #offClassObject_super]     @ r1<- method->clazz->super
9365    ldrh    r2, [r0, #offMethod_methodIndex]    @ r2<- baseMethod->methodIndex
9366    ldr     r3, [r1, #offClassObject_vtableCount]   @ r3<- super->vtableCount
9367    EXPORT_PC()                         @ must export for invoke
9368    cmp     r2, r3                      @ compare (methodIndex, vtableCount)
9369    bcs     .LOP_INVOKE_SUPER_RANGE_nsm             @ method not present in superclass
9370    ldr     r1, [r1, #offClassObject_vtable]    @ r1<- ...clazz->super->vtable
9371    ldr     r0, [r1, r2, lsl #2]        @ r3<- vtable[methodIndex]
9372    bl      common_invokeMethodRange @ continue on
9373
9374.LOP_INVOKE_SUPER_RANGE_resolve:
9375    mov     r0, r9                      @ r0<- method->clazz
9376    mov     r2, #METHOD_VIRTUAL         @ resolver method type
9377    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9378    cmp     r0, #0                      @ got null?
9379    bne     .LOP_INVOKE_SUPER_RANGE_continue        @ no, continue
9380    b       common_exceptionThrown      @ yes, handle exception
9381
9382    /*
9383     * Throw a NoSuchMethodError with the method name as the message.
9384     *  r0 = resolved base method
9385     */
9386.LOP_INVOKE_SUPER_RANGE_nsm:
9387    ldr     r1, [r0, #offMethod_name]   @ r1<- method name
9388    b       common_errNoSuchMethod
9389
9390/* continuation for OP_INVOKE_DIRECT_RANGE */
9391
9392    /*
9393     * On entry:
9394     *  r1 = reference (BBBB or CCCC)
9395     *  r10 = "this" register
9396     */
9397.LOP_INVOKE_DIRECT_RANGE_resolve:
9398    ldr     r3, [rGLUE, #offGlue_method] @ r3<- glue->method
9399    ldr     r0, [r3, #offMethod_clazz]  @ r0<- method->clazz
9400    mov     r2, #METHOD_DIRECT          @ resolver method type
9401    bl      dvmResolveMethod            @ r0<- call(clazz, ref, flags)
9402    cmp     r0, #0                      @ got null?
9403    GET_VREG(r2, r10)                   @ r2<- "this" ptr (reload)
9404    bne     .LOP_INVOKE_DIRECT_RANGE_finish          @ no, continue
9405    b       common_exceptionThrown      @ yes, handle exception
9406
9407/* continuation for OP_FLOAT_TO_LONG */
9408/*
9409 * Convert the float in r0 to a long in r0/r1.
9410 *
9411 * We have to clip values to long min/max per the specification.  The
9412 * expected common case is a "reasonable" value that converts directly
9413 * to modest integer.  The EABI convert function isn't doing this for us.
9414 */
9415f2l_doconv:
9416    stmfd   sp!, {r4, lr}
9417    mov     r1, #0x5f000000             @ (float)maxlong
9418    mov     r4, r0
9419    bl      __aeabi_fcmpge              @ is arg >= maxlong?
9420    cmp     r0, #0                      @ nonzero == yes
9421    mvnne   r0, #0                      @ return maxlong (7fffffff)
9422    mvnne   r1, #0x80000000
9423    ldmnefd sp!, {r4, pc}
9424
9425    mov     r0, r4                      @ recover arg
9426    mov     r1, #0xdf000000             @ (float)minlong
9427    bl      __aeabi_fcmple              @ is arg <= minlong?
9428    cmp     r0, #0                      @ nonzero == yes
9429    movne   r0, #0                      @ return minlong (80000000)
9430    movne   r1, #0x80000000
9431    ldmnefd sp!, {r4, pc}
9432
9433    mov     r0, r4                      @ recover arg
9434    mov     r1, r4
9435    bl      __aeabi_fcmpeq              @ is arg == self?
9436    cmp     r0, #0                      @ zero == no
9437    moveq   r1, #0                      @ return zero for NaN
9438    ldmeqfd sp!, {r4, pc}
9439
9440    mov     r0, r4                      @ recover arg
9441    bl      __aeabi_f2lz                @ convert float to long
9442    ldmfd   sp!, {r4, pc}
9443
9444/* continuation for OP_DOUBLE_TO_LONG */
9445/*
9446 * Convert the double in r0/r1 to a long in r0/r1.
9447 *
9448 * We have to clip values to long min/max per the specification.  The
9449 * expected common case is a "reasonable" value that converts directly
9450 * to modest integer.  The EABI convert function isn't doing this for us.
9451 */
9452d2l_doconv:
9453    stmfd   sp!, {r4, r5, lr}           @ save regs
9454    mov     r3, #0x43000000             @ maxlong, as a double (high word)
9455    add     r3, #0x00e00000             @  0x43e00000
9456    mov     r2, #0                      @ maxlong, as a double (low word)
9457    sub     sp, sp, #4                  @ align for EABI
9458    mov     r4, r0                      @ save a copy of r0
9459    mov     r5, r1                      @  and r1
9460    bl      __aeabi_dcmpge              @ is arg >= maxlong?
9461    cmp     r0, #0                      @ nonzero == yes
9462    mvnne   r0, #0                      @ return maxlong (7fffffffffffffff)
9463    mvnne   r1, #0x80000000
9464    bne     1f
9465
9466    mov     r0, r4                      @ recover arg
9467    mov     r1, r5
9468    mov     r3, #0xc3000000             @ minlong, as a double (high word)
9469    add     r3, #0x00e00000             @  0xc3e00000
9470    mov     r2, #0                      @ minlong, as a double (low word)
9471    bl      __aeabi_dcmple              @ is arg <= minlong?
9472    cmp     r0, #0                      @ nonzero == yes
9473    movne   r0, #0                      @ return minlong (8000000000000000)
9474    movne   r1, #0x80000000
9475    bne     1f
9476
9477    mov     r0, r4                      @ recover arg
9478    mov     r1, r5
9479    mov     r2, r4                      @ compare against self
9480    mov     r3, r5
9481    bl      __aeabi_dcmpeq              @ is arg == self?
9482    cmp     r0, #0                      @ zero == no
9483    moveq   r1, #0                      @ return zero for NaN
9484    beq     1f
9485
9486    mov     r0, r4                      @ recover arg
9487    mov     r1, r5
9488    bl      __aeabi_d2lz                @ convert double to long
9489
94901:
9491    add     sp, sp, #4
9492    ldmfd   sp!, {r4, r5, pc}
9493
9494/* continuation for OP_MUL_LONG */
9495
9496.LOP_MUL_LONG_finish:
9497    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9498    stmia   r0, {r9-r10}                @ vAA/vAA+1<- r9/r10
9499    GOTO_OPCODE(ip)                     @ jump to next instruction
9500
9501/* continuation for OP_SHL_LONG */
9502
9503.LOP_SHL_LONG_finish:
9504    mov     r0, r0, asl r2              @  r0<- r0 << r2
9505    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9506    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9507    GOTO_OPCODE(ip)                     @ jump to next instruction
9508
9509/* continuation for OP_SHR_LONG */
9510
9511.LOP_SHR_LONG_finish:
9512    mov     r1, r1, asr r2              @  r1<- r1 >> r2
9513    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9514    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9515    GOTO_OPCODE(ip)                     @ jump to next instruction
9516
9517/* continuation for OP_USHR_LONG */
9518
9519.LOP_USHR_LONG_finish:
9520    mov     r1, r1, lsr r2              @  r1<- r1 >>> r2
9521    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9522    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9523    GOTO_OPCODE(ip)                     @ jump to next instruction
9524
9525/* continuation for OP_SHL_LONG_2ADDR */
9526
9527.LOP_SHL_LONG_2ADDR_finish:
9528    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9529    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9530    GOTO_OPCODE(ip)                     @ jump to next instruction
9531
9532/* continuation for OP_SHR_LONG_2ADDR */
9533
9534.LOP_SHR_LONG_2ADDR_finish:
9535    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9536    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9537    GOTO_OPCODE(ip)                     @ jump to next instruction
9538
9539/* continuation for OP_USHR_LONG_2ADDR */
9540
9541.LOP_USHR_LONG_2ADDR_finish:
9542    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9543    stmia   r9, {r0-r1}                 @ vAA/vAA+1<- r0/r1
9544    GOTO_OPCODE(ip)                     @ jump to next instruction
9545
9546/* continuation for OP_IGET_VOLATILE */
9547
9548    /*
9549     * Currently:
9550     *  r0 holds resolved field
9551     *  r9 holds object
9552     */
9553.LOP_IGET_VOLATILE_finish:
9554    @bl      common_squeak0
9555    cmp     r9, #0                      @ check object for null
9556    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9557    beq     common_errNullObject        @ object was null
9558    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9559    SMP_DMB                            @ acquiring load
9560    mov     r2, rINST, lsr #8           @ r2<- A+
9561    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9562    and     r2, r2, #15                 @ r2<- A
9563    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9564    SET_VREG(r0, r2)                    @ fp[A]<- r0
9565    GOTO_OPCODE(ip)                     @ jump to next instruction
9566
9567/* continuation for OP_IPUT_VOLATILE */
9568
9569    /*
9570     * Currently:
9571     *  r0 holds resolved field
9572     *  r9 holds object
9573     */
9574.LOP_IPUT_VOLATILE_finish:
9575    @bl      common_squeak0
9576    mov     r1, rINST, lsr #8           @ r1<- A+
9577    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9578    and     r1, r1, #15                 @ r1<- A
9579    cmp     r9, #0                      @ check object for null
9580    GET_VREG(r0, r1)                    @ r0<- fp[A]
9581    beq     common_errNullObject        @ object was null
9582    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9583    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9584    SMP_DMB                            @ releasing store
9585    str  r0, [r9, r3]                @ obj.field (8/16/32 bits)<- r0
9586    GOTO_OPCODE(ip)                     @ jump to next instruction
9587
9588/* continuation for OP_SGET_VOLATILE */
9589
9590    /*
9591     * Continuation if the field has not yet been resolved.
9592     *  r1: BBBB field ref
9593     */
9594.LOP_SGET_VOLATILE_resolve:
9595    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9596    EXPORT_PC()                         @ resolve() could throw, so export now
9597    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9598    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9599    cmp     r0, #0                      @ success?
9600    bne     .LOP_SGET_VOLATILE_finish          @ yes, finish
9601    b       common_exceptionThrown      @ no, handle exception
9602
9603/* continuation for OP_SPUT_VOLATILE */
9604
9605    /*
9606     * Continuation if the field has not yet been resolved.
9607     *  r1: BBBB field ref
9608     */
9609.LOP_SPUT_VOLATILE_resolve:
9610    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9611    EXPORT_PC()                         @ resolve() could throw, so export now
9612    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9613    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9614    cmp     r0, #0                      @ success?
9615    bne     .LOP_SPUT_VOLATILE_finish          @ yes, finish
9616    b       common_exceptionThrown      @ no, handle exception
9617
9618/* continuation for OP_IGET_OBJECT_VOLATILE */
9619
9620    /*
9621     * Currently:
9622     *  r0 holds resolved field
9623     *  r9 holds object
9624     */
9625.LOP_IGET_OBJECT_VOLATILE_finish:
9626    @bl      common_squeak0
9627    cmp     r9, #0                      @ check object for null
9628    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9629    beq     common_errNullObject        @ object was null
9630    ldr   r0, [r9, r3]                @ r0<- obj.field (8/16/32 bits)
9631    SMP_DMB                            @ acquiring load
9632    mov     r2, rINST, lsr #8           @ r2<- A+
9633    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9634    and     r2, r2, #15                 @ r2<- A
9635    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9636    SET_VREG(r0, r2)                    @ fp[A]<- r0
9637    GOTO_OPCODE(ip)                     @ jump to next instruction
9638
9639/* continuation for OP_IGET_WIDE_VOLATILE */
9640
9641    /*
9642     * Currently:
9643     *  r0 holds resolved field
9644     *  r9 holds object
9645     */
9646.LOP_IGET_WIDE_VOLATILE_finish:
9647    cmp     r9, #0                      @ check object for null
9648    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9649    beq     common_errNullObject        @ object was null
9650    .if 1
9651    add     r0, r9, r3                  @ r0<- address of field
9652    bl      dvmQuasiAtomicRead64        @ r0/r1<- contents of field
9653    .else
9654    add     r9, r9, r3                  @ r9<- obj + field offset
9655    ldmia   r9, {r0-r1}                 @ r0/r1<- obj.field (64-bit align ok)
9656    .endif
9657    mov     r2, rINST, lsr #8           @ r2<- A+
9658    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9659    and     r2, r2, #15                 @ r2<- A
9660    add     r3, rFP, r2, lsl #2         @ r3<- &fp[A]
9661    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9662    stmia   r3, {r0-r1}                 @ fp[A]<- r0/r1
9663    GOTO_OPCODE(ip)                     @ jump to next instruction
9664
9665/* continuation for OP_IPUT_WIDE_VOLATILE */
9666
9667    /*
9668     * Currently:
9669     *  r0 holds resolved field
9670     *  r9 holds object
9671     */
9672.LOP_IPUT_WIDE_VOLATILE_finish:
9673    mov     r2, rINST, lsr #8           @ r2<- A+
9674    cmp     r9, #0                      @ check object for null
9675    and     r2, r2, #15                 @ r2<- A
9676    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9677    add     r2, rFP, r2, lsl #2         @ r3<- &fp[A]
9678    beq     common_errNullObject        @ object was null
9679    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9680    ldmia   r2, {r0-r1}                 @ r0/r1<- fp[A]
9681    GET_INST_OPCODE(r10)                @ extract opcode from rINST
9682    add     r2, r9, r3                  @ r2<- object + byte offset
9683    .if 1
9684    bl      dvmQuasiAtomicSwap64        @ stores r0/r1 into addr r2
9685    .else
9686    stmia   r2, {r0-r1}                 @ obj.field (64 bits, aligned)<- r0/r1
9687    .endif
9688    GOTO_OPCODE(r10)                    @ jump to next instruction
9689
9690/* continuation for OP_SGET_WIDE_VOLATILE */
9691
9692    /*
9693     * Continuation if the field has not yet been resolved.
9694     *  r1: BBBB field ref
9695     *
9696     * Returns StaticField pointer in r0.
9697     */
9698.LOP_SGET_WIDE_VOLATILE_resolve:
9699    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9700    EXPORT_PC()                         @ resolve() could throw, so export now
9701    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9702    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9703    cmp     r0, #0                      @ success?
9704    bne     .LOP_SGET_WIDE_VOLATILE_finish          @ yes, finish
9705    b       common_exceptionThrown      @ no, handle exception
9706
9707/* continuation for OP_SPUT_WIDE_VOLATILE */
9708
9709    /*
9710     * Continuation if the field has not yet been resolved.
9711     *  r1: BBBB field ref
9712     *  r9: &fp[AA]
9713     *
9714     * Returns StaticField pointer in r2.
9715     */
9716.LOP_SPUT_WIDE_VOLATILE_resolve:
9717    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9718    EXPORT_PC()                         @ resolve() could throw, so export now
9719    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9720    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9721    cmp     r0, #0                      @ success?
9722    mov     r2, r0                      @ copy to r2
9723    bne     .LOP_SPUT_WIDE_VOLATILE_finish          @ yes, finish
9724    b       common_exceptionThrown      @ no, handle exception
9725
9726/* continuation for OP_EXECUTE_INLINE */
9727
9728    /*
9729     * Extract args, call function.
9730     *  r0 = #of args (0-4)
9731     *  r10 = call index
9732     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9733     *
9734     * Other ideas:
9735     * - Use a jump table from the main piece to jump directly into the
9736     *   AND/LDR pairs.  Costs a data load, saves a branch.
9737     * - Have five separate pieces that do the loading, so we can work the
9738     *   interleave a little better.  Increases code size.
9739     */
9740.LOP_EXECUTE_INLINE_continue:
9741    rsb     r0, r0, #4                  @ r0<- 4-r0
9742    FETCH(r9, 2)                        @ r9<- FEDC
9743    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9744    bl      common_abort                @ (skipped due to ARM prefetch)
97454:  and     ip, r9, #0xf000             @ isolate F
9746    ldr     r3, [rFP, ip, lsr #10]      @ r3<- vF (shift right 12, left 2)
97473:  and     ip, r9, #0x0f00             @ isolate E
9748    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vE
97492:  and     ip, r9, #0x00f0             @ isolate D
9750    ldr     r1, [rFP, ip, lsr #2]       @ r1<- vD
97511:  and     ip, r9, #0x000f             @ isolate C
9752    ldr     r0, [rFP, ip, lsl #2]       @ r0<- vC
97530:
9754    ldr     r9, .LOP_EXECUTE_INLINE_table       @ table of InlineOperation
9755    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9756    @ (not reached)
9757
9758.LOP_EXECUTE_INLINE_table:
9759    .word   gDvmInlineOpsTable
9760
9761/* continuation for OP_EXECUTE_INLINE_RANGE */
9762
9763    /*
9764     * Extract args, call function.
9765     *  r0 = #of args (0-4)
9766     *  r10 = call index
9767     *  lr = return addr, above  [DO NOT bl out of here w/o preserving LR]
9768     */
9769.LOP_EXECUTE_INLINE_RANGE_continue:
9770    rsb     r0, r0, #4                  @ r0<- 4-r0
9771    FETCH(r9, 2)                        @ r9<- CCCC
9772    add     pc, pc, r0, lsl #3          @ computed goto, 2 instrs each
9773    bl      common_abort                @ (skipped due to ARM prefetch)
97744:  add     ip, r9, #3                  @ base+3
9775    GET_VREG(r3, ip)                    @ r3<- vBase[3]
97763:  add     ip, r9, #2                  @ base+2
9777    GET_VREG(r2, ip)                    @ r2<- vBase[2]
97782:  add     ip, r9, #1                  @ base+1
9779    GET_VREG(r1, ip)                    @ r1<- vBase[1]
97801:  add     ip, r9, #0                  @ (nop)
9781    GET_VREG(r0, ip)                    @ r0<- vBase[0]
97820:
9783    ldr     r9, .LOP_EXECUTE_INLINE_RANGE_table       @ table of InlineOperation
9784    LDR_PC  "[r9, r10, lsl #4]"         @ sizeof=16, "func" is first entry
9785    @ (not reached)
9786
9787.LOP_EXECUTE_INLINE_RANGE_table:
9788    .word   gDvmInlineOpsTable
9789
9790/* continuation for OP_IPUT_OBJECT_VOLATILE */
9791
9792    /*
9793     * Currently:
9794     *  r0 holds resolved field
9795     *  r9 holds object
9796     */
9797.LOP_IPUT_OBJECT_VOLATILE_finish:
9798    @bl      common_squeak0
9799    mov     r1, rINST, lsr #8           @ r1<- A+
9800    ldr     r3, [r0, #offInstField_byteOffset]  @ r3<- byte offset of field
9801    and     r1, r1, #15                 @ r1<- A
9802    cmp     r9, #0                      @ check object for null
9803    GET_VREG(r0, r1)                    @ r0<- fp[A]
9804    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9805    beq     common_errNullObject        @ object was null
9806    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9807    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9808    SMP_DMB                            @ releasing store
9809    str     r0, [r9, r3]                @ obj.field (32 bits)<- r0
9810    cmp     r0, #0                      @ stored a null reference?
9811    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card if not
9812    GOTO_OPCODE(ip)                     @ jump to next instruction
9813
9814/* continuation for OP_SGET_OBJECT_VOLATILE */
9815
9816    /*
9817     * Continuation if the field has not yet been resolved.
9818     *  r1: BBBB field ref
9819     */
9820.LOP_SGET_OBJECT_VOLATILE_resolve:
9821    ldr     r2, [rGLUE, #offGlue_method]    @ r2<- current method
9822    EXPORT_PC()                         @ resolve() could throw, so export now
9823    ldr     r0, [r2, #offMethod_clazz]  @ r0<- method->clazz
9824    bl      dvmResolveStaticField       @ r0<- resolved StaticField ptr
9825    cmp     r0, #0                      @ success?
9826    bne     .LOP_SGET_OBJECT_VOLATILE_finish          @ yes, finish
9827    b       common_exceptionThrown      @ no, handle exception
9828
9829/* continuation for OP_SPUT_OBJECT_VOLATILE */
9830.LOP_SPUT_OBJECT_VOLATILE_finish:   @ field ptr in r0
9831    mov     r2, rINST, lsr #8           @ r2<- AA
9832    FETCH_ADVANCE_INST(2)               @ advance rPC, load rINST
9833    GET_VREG(r1, r2)                    @ r1<- fp[AA]
9834    ldr     r2, [rGLUE, #offGlue_cardTable]  @ r2<- card table base
9835    ldr     r9, [r0, #offField_clazz]   @ r9<- field->clazz
9836    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
9837    SMP_DMB                            @ releasing store
9838    str     r1, [r0, #offStaticField_value]  @ field<- vAA
9839    cmp     r1, #0                      @ stored a null object?
9840    strneb  r2, [r2, r9, lsr #GC_CARD_SHIFT]  @ mark card based on obj head
9841    GOTO_OPCODE(ip)                     @ jump to next instruction
9842
9843    .size   dvmAsmSisterStart, .-dvmAsmSisterStart
9844    .global dvmAsmSisterEnd
9845dvmAsmSisterEnd:
9846
9847/* File: armv5te/footer.S */
9848
9849/*
9850 * ===========================================================================
9851 *  Common subroutines and data
9852 * ===========================================================================
9853 */
9854
9855
9856
9857    .text
9858    .align  2
9859
9860#if defined(WITH_JIT)
9861#if defined(WITH_SELF_VERIFICATION)
9862    .global dvmJitToInterpPunt
9863dvmJitToInterpPunt:
9864    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9865    mov    r2,#kSVSPunt                 @ r2<- interpreter entry point
9866    mov    r3, #0
9867    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9868    b      jitSVShadowRunEnd            @ doesn't return
9869
9870    .global dvmJitToInterpSingleStep
9871dvmJitToInterpSingleStep:
9872    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9873    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9874    mov    r2,#kSVSSingleStep           @ r2<- interpreter entry point
9875    b      jitSVShadowRunEnd            @ doesn't return
9876
9877    .global dvmJitToInterpNoChainNoProfile
9878dvmJitToInterpNoChainNoProfile:
9879    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9880    mov    r0,rPC                       @ pass our target PC
9881    mov    r2,#kSVSNoProfile            @ r2<- interpreter entry point
9882    mov    r3, #0                       @ 0 means !inJitCodeCache
9883    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
9884    b      jitSVShadowRunEnd            @ doesn't return
9885
9886    .global dvmJitToInterpTraceSelectNoChain
9887dvmJitToInterpTraceSelectNoChain:
9888    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9889    mov    r0,rPC                       @ pass our target PC
9890    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9891    mov    r3, #0                       @ 0 means !inJitCodeCache
9892    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9893    b      jitSVShadowRunEnd            @ doesn't return
9894
9895    .global dvmJitToInterpTraceSelect
9896dvmJitToInterpTraceSelect:
9897    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9898    ldr    r0,[lr, #-1]                 @ pass our target PC
9899    mov    r2,#kSVSTraceSelect          @ r2<- interpreter entry point
9900    mov    r3, #0                       @ 0 means !inJitCodeCache
9901    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9902    b      jitSVShadowRunEnd            @ doesn't return
9903
9904    .global dvmJitToInterpBackwardBranch
9905dvmJitToInterpBackwardBranch:
9906    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9907    ldr    r0,[lr, #-1]                 @ pass our target PC
9908    mov    r2,#kSVSBackwardBranch       @ r2<- interpreter entry point
9909    mov    r3, #0                       @ 0 means !inJitCodeCache
9910    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9911    b      jitSVShadowRunEnd            @ doesn't return
9912
9913    .global dvmJitToInterpNormal
9914dvmJitToInterpNormal:
9915    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9916    ldr    r0,[lr, #-1]                 @ pass our target PC
9917    mov    r2,#kSVSNormal               @ r2<- interpreter entry point
9918    mov    r3, #0                       @ 0 means !inJitCodeCache
9919    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9920    b      jitSVShadowRunEnd            @ doesn't return
9921
9922    .global dvmJitToInterpNoChain
9923dvmJitToInterpNoChain:
9924    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9925    mov    r0,rPC                       @ pass our target PC
9926    mov    r2,#kSVSNoChain              @ r2<- interpreter entry point
9927    mov    r3, #0                       @ 0 means !inJitCodeCache
9928    str    r3, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9929    b      jitSVShadowRunEnd            @ doesn't return
9930#else
9931/*
9932 * Return from the translation cache to the interpreter when the compiler is
9933 * having issues translating/executing a Dalvik instruction. We have to skip
9934 * the code cache lookup otherwise it is possible to indefinitely bouce
9935 * between the interpreter and the code cache if the instruction that fails
9936 * to be compiled happens to be at a trace start.
9937 */
9938    .global dvmJitToInterpPunt
9939dvmJitToInterpPunt:
9940    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9941    mov    rPC, r0
9942#if defined(WITH_JIT_TUNING)
9943    mov    r0,lr
9944    bl     dvmBumpPunt;
9945#endif
9946    EXPORT_PC()
9947    mov    r0, #0
9948    str    r0, [r10, #offThread_inJitCodeCache] @ Back to the interp land
9949    adrl   rIBASE, dvmAsmInstructionStart
9950    FETCH_INST()
9951    GET_INST_OPCODE(ip)
9952    GOTO_OPCODE(ip)
9953
9954/*
9955 * Return to the interpreter to handle a single instruction.
9956 * On entry:
9957 *    r0 <= PC
9958 *    r1 <= PC of resume instruction
9959 *    lr <= resume point in translation
9960 */
9961    .global dvmJitToInterpSingleStep
9962dvmJitToInterpSingleStep:
9963    str    lr,[rGLUE,#offGlue_jitResumeNPC]
9964    str    r1,[rGLUE,#offGlue_jitResumeDPC]
9965    mov    r1,#kInterpEntryInstr
9966    @ enum is 4 byte in aapcs-EABI
9967    str    r1, [rGLUE, #offGlue_entryPoint]
9968    mov    rPC,r0
9969    EXPORT_PC()
9970
9971    adrl   rIBASE, dvmAsmInstructionStart
9972    mov    r2,#kJitSingleStep     @ Ask for single step and then revert
9973    str    r2,[rGLUE,#offGlue_jitState]
9974    mov    r1,#1                  @ set changeInterp to bail to debug interp
9975    b      common_gotoBail
9976
9977/*
9978 * Return from the translation cache and immediately request
9979 * a translation for the exit target.  Commonly used for callees.
9980 */
9981    .global dvmJitToInterpTraceSelectNoChain
9982dvmJitToInterpTraceSelectNoChain:
9983#if defined(WITH_JIT_TUNING)
9984    bl     dvmBumpNoChain
9985#endif
9986    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
9987    mov    r0,rPC
9988    bl     dvmJitGetCodeAddr        @ Is there a translation?
9989    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
9990    mov    r1, rPC                  @ arg1 of translation may need this
9991    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
9992    cmp    r0,#0                    @ !0 means translation exists
9993    bxne   r0                       @ continue native execution if so
9994    b      2f                       @ branch over to use the interpreter
9995
9996/*
9997 * Return from the translation cache and immediately request
9998 * a translation for the exit target.  Commonly used following
9999 * invokes.
10000 */
10001    .global dvmJitToInterpTraceSelect
10002dvmJitToInterpTraceSelect:
10003    ldr    rPC,[lr, #-1]           @ get our target PC
10004    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
10005    add    rINST,lr,#-5            @ save start of chain branch
10006    add    rINST, #-4              @  .. which is 9 bytes back
10007    mov    r0,rPC
10008    bl     dvmJitGetCodeAddr       @ Is there a translation?
10009    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
10010    cmp    r0,#0
10011    beq    2f
10012    mov    r1,rINST
10013    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
10014    mov    r1, rPC                  @ arg1 of translation may need this
10015    mov    lr, #0                   @ in case target is HANDLER_INTERPRET
10016    cmp    r0,#0                    @ successful chain?
10017    bxne   r0                       @ continue native execution
10018    b      toInterpreter            @ didn't chain - resume with interpreter
10019
10020/* No translation, so request one if profiling isn't disabled*/
100212:
10022    adrl   rIBASE, dvmAsmInstructionStart
10023    GET_JIT_PROF_TABLE(r0)
10024    FETCH_INST()
10025    cmp    r0, #0
10026    movne  r2,#kJitTSelectRequestHot   @ ask for trace selection
10027    bne    common_selectTrace
10028    GET_INST_OPCODE(ip)
10029    GOTO_OPCODE(ip)
10030
10031/*
10032 * Return from the translation cache to the interpreter.
10033 * The return was done with a BLX from thumb mode, and
10034 * the following 32-bit word contains the target rPC value.
10035 * Note that lr (r14) will have its low-order bit set to denote
10036 * its thumb-mode origin.
10037 *
10038 * We'll need to stash our lr origin away, recover the new
10039 * target and then check to see if there is a translation available
10040 * for our new target.  If so, we do a translation chain and
10041 * go back to native execution.  Otherwise, it's back to the
10042 * interpreter (after treating this entry as a potential
10043 * trace start).
10044 */
10045    .global dvmJitToInterpNormal
10046dvmJitToInterpNormal:
10047    ldr    rPC,[lr, #-1]           @ get our target PC
10048    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
10049    add    rINST,lr,#-5            @ save start of chain branch
10050    add    rINST,#-4               @ .. which is 9 bytes back
10051#if defined(WITH_JIT_TUNING)
10052    bl     dvmBumpNormal
10053#endif
10054    mov    r0,rPC
10055    bl     dvmJitGetCodeAddr        @ Is there a translation?
10056    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
10057    cmp    r0,#0
10058    beq    toInterpreter            @ go if not, otherwise do chain
10059    mov    r1,rINST
10060    bl     dvmJitChain              @ r0<- dvmJitChain(codeAddr,chainAddr)
10061    mov    r1, rPC                  @ arg1 of translation may need this
10062    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
10063    cmp    r0,#0                    @ successful chain?
10064    bxne   r0                       @ continue native execution
10065    b      toInterpreter            @ didn't chain - resume with interpreter
10066
10067/*
10068 * Return from the translation cache to the interpreter to do method invocation.
10069 * Check if translation exists for the callee, but don't chain to it.
10070 */
10071    .global dvmJitToInterpNoChainNoProfile
10072dvmJitToInterpNoChainNoProfile:
10073#if defined(WITH_JIT_TUNING)
10074    bl     dvmBumpNoChain
10075#endif
10076    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
10077    mov    r0,rPC
10078    bl     dvmJitGetCodeAddr        @ Is there a translation?
10079    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
10080    mov    r1, rPC                  @ arg1 of translation may need this
10081    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
10082    cmp    r0,#0
10083    bxne   r0                       @ continue native execution if so
10084    EXPORT_PC()
10085    adrl   rIBASE, dvmAsmInstructionStart
10086    FETCH_INST()
10087    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10088    GOTO_OPCODE(ip)                     @ jump to next instruction
10089
10090/*
10091 * Return from the translation cache to the interpreter to do method invocation.
10092 * Check if translation exists for the callee, but don't chain to it.
10093 */
10094    .global dvmJitToInterpNoChain
10095dvmJitToInterpNoChain:
10096#if defined(WITH_JIT_TUNING)
10097    bl     dvmBumpNoChain
10098#endif
10099    ldr    r10, [rGLUE, #offGlue_self]  @ callee saved r10 <- glue->self
10100    mov    r0,rPC
10101    bl     dvmJitGetCodeAddr        @ Is there a translation?
10102    str    r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
10103    mov    r1, rPC                  @ arg1 of translation may need this
10104    mov    lr, #0                   @  in case target is HANDLER_INTERPRET
10105    cmp    r0,#0
10106    bxne   r0                       @ continue native execution if so
10107#endif
10108
10109/*
10110 * No translation, restore interpreter regs and start interpreting.
10111 * rGLUE & rFP were preserved in the translated code, and rPC has
10112 * already been restored by the time we get here.  We'll need to set
10113 * up rIBASE & rINST, and load the address of the JitTable into r0.
10114 */
10115toInterpreter:
10116    EXPORT_PC()
10117    adrl   rIBASE, dvmAsmInstructionStart
10118    FETCH_INST()
10119    GET_JIT_PROF_TABLE(r0)
10120    @ NOTE: intended fallthrough
10121
10122/*
10123 * Common code to update potential trace start counter, and initiate
10124 * a trace-build if appropriate.  On entry, rPC should point to the
10125 * next instruction to execute, and rINST should be already loaded with
10126 * the next opcode word, and r0 holds a pointer to the jit profile
10127 * table (pJitProfTable).
10128 */
10129common_testUpdateProfile:
10130    cmp     r0,#0
10131    GET_INST_OPCODE(ip)
10132    GOTO_OPCODE_IFEQ(ip)       @ if not profiling, fallthrough otherwise */
10133
10134common_updateProfile:
10135    eor     r3,rPC,rPC,lsr #12 @ cheap, but fast hash function
10136    lsl     r3,r3,#(32 - JIT_PROF_SIZE_LOG_2)          @ shift out excess bits
10137    ldrb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ get counter
10138    GET_INST_OPCODE(ip)
10139    subs    r1,r1,#1           @ decrement counter
10140    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ and store it
10141    GOTO_OPCODE_IFNE(ip)       @ if not threshold, fallthrough otherwise */
10142
10143/*
10144 * Here, we switch to the debug interpreter to request
10145 * trace selection.  First, though, check to see if there
10146 * is already a native translation in place (and, if so,
10147 * jump to it now).
10148 */
10149    GET_JIT_THRESHOLD(r1)
10150    ldr     r10, [rGLUE, #offGlue_self] @ callee saved r10 <- glue->self
10151    strb    r1,[r0,r3,lsr #(32 - JIT_PROF_SIZE_LOG_2)] @ reset counter
10152    EXPORT_PC()
10153    mov     r0,rPC
10154    bl      dvmJitGetCodeAddr           @ r0<- dvmJitGetCodeAddr(rPC)
10155    str     r0, [r10, #offThread_inJitCodeCache] @ set the inJitCodeCache flag
10156    mov     r1, rPC                     @ arg1 of translation may need this
10157    mov     lr, #0                      @  in case target is HANDLER_INTERPRET
10158    cmp     r0,#0
10159#if !defined(WITH_SELF_VERIFICATION)
10160    bxne    r0                          @ jump to the translation
10161    mov     r2,#kJitTSelectRequest      @ ask for trace selection
10162    @ fall-through to common_selectTrace
10163#else
10164    moveq   r2,#kJitTSelectRequest      @ ask for trace selection
10165    beq     common_selectTrace
10166    /*
10167     * At this point, we have a target translation.  However, if
10168     * that translation is actually the interpret-only pseudo-translation
10169     * we want to treat it the same as no translation.
10170     */
10171    mov     r10, r0                     @ save target
10172    bl      dvmCompilerGetInterpretTemplate
10173    cmp     r0, r10                     @ special case?
10174    bne     jitSVShadowRunStart         @ set up self verification shadow space
10175    @ Need to clear the inJitCodeCache flag
10176    ldr    r10, [rGLUE, #offGlue_self]  @ r10 <- glue->self
10177    mov    r3, #0                       @ 0 means not in the JIT code cache
10178    str    r3, [r10, #offThread_inJitCodeCache] @ back to the interp land
10179    GET_INST_OPCODE(ip)
10180    GOTO_OPCODE(ip)
10181    /* no return */
10182#endif
10183
10184/*
10185 * On entry:
10186 *  r2 is jit state, e.g. kJitTSelectRequest or kJitTSelectRequestHot
10187 */
10188common_selectTrace:
10189    str     r2,[rGLUE,#offGlue_jitState]
10190    mov     r2,#kInterpEntryInstr       @ normal entry reason
10191    str     r2,[rGLUE,#offGlue_entryPoint]
10192    mov     r1,#1                       @ set changeInterp
10193    b       common_gotoBail
10194
10195#if defined(WITH_SELF_VERIFICATION)
10196/*
10197 * Save PC and registers to shadow memory for self verification mode
10198 * before jumping to native translation.
10199 * On entry:
10200 *    rPC, rFP, rGLUE: the values that they should contain
10201 *    r10: the address of the target translation.
10202 */
10203jitSVShadowRunStart:
10204    mov     r0,rPC                      @ r0<- program counter
10205    mov     r1,rFP                      @ r1<- frame pointer
10206    mov     r2,rGLUE                    @ r2<- InterpState pointer
10207    mov     r3,r10                      @ r3<- target translation
10208    bl      dvmSelfVerificationSaveState @ save registers to shadow space
10209    ldr     rFP,[r0,#offShadowSpace_shadowFP] @ rFP<- fp in shadow space
10210    add     rGLUE,r0,#offShadowSpace_interpState @ rGLUE<- rGLUE in shadow space
10211    bx      r10                         @ jump to the translation
10212
10213/*
10214 * Restore PC, registers, and interpState to original values
10215 * before jumping back to the interpreter.
10216 */
10217jitSVShadowRunEnd:
10218    mov    r1,rFP                        @ pass ending fp
10219    bl     dvmSelfVerificationRestoreState @ restore pc and fp values
10220    ldr    rPC,[r0,#offShadowSpace_startPC] @ restore PC
10221    ldr    rFP,[r0,#offShadowSpace_fp]   @ restore FP
10222    ldr    rGLUE,[r0,#offShadowSpace_glue] @ restore InterpState
10223    ldr    r1,[r0,#offShadowSpace_svState] @ get self verification state
10224    cmp    r1,#0                         @ check for punt condition
10225    beq    1f
10226    mov    r2,#kJitSelfVerification      @ ask for self verification
10227    str    r2,[rGLUE,#offGlue_jitState]
10228    mov    r2,#kInterpEntryInstr         @ normal entry reason
10229    str    r2,[rGLUE,#offGlue_entryPoint]
10230    mov    r1,#1                         @ set changeInterp
10231    b      common_gotoBail
10232
102331:                                       @ exit to interpreter without check
10234    EXPORT_PC()
10235    adrl   rIBASE, dvmAsmInstructionStart
10236    FETCH_INST()
10237    GET_INST_OPCODE(ip)
10238    GOTO_OPCODE(ip)
10239#endif
10240
10241#endif
10242
10243/*
10244 * Common code when a backward branch is taken.
10245 *
10246 * TODO: we could avoid a branch by just setting r0 and falling through
10247 * into the common_periodicChecks code, and having a test on r0 at the
10248 * end determine if we should return to the caller or update & branch to
10249 * the next instr.
10250 *
10251 * On entry:
10252 *  r9 is PC adjustment *in bytes*
10253 */
10254common_backwardBranch:
10255    mov     r0, #kInterpEntryInstr
10256    bl      common_periodicChecks
10257#if defined(WITH_JIT)
10258    GET_JIT_PROF_TABLE(r0)
10259    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
10260    cmp     r0,#0
10261    bne     common_updateProfile
10262    GET_INST_OPCODE(ip)
10263    GOTO_OPCODE(ip)
10264#else
10265    FETCH_ADVANCE_INST_RB(r9)           @ update rPC, load rINST
10266    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10267    GOTO_OPCODE(ip)                     @ jump to next instruction
10268#endif
10269
10270
10271/*
10272 * Need to see if the thread needs to be suspended or debugger/profiler
10273 * activity has begun.  If so, we suspend the thread or side-exit to
10274 * the debug interpreter as appropriate.
10275 *
10276 * The common case is no activity on any of these, so we want to figure
10277 * that out quickly.  If something is up, we can then sort out what.
10278 *
10279 * We want to be fast if the VM was built without debugger or profiler
10280 * support, but we also need to recognize that the system is usually
10281 * shipped with both of these enabled.
10282 *
10283 * TODO: reduce this so we're just checking a single location.
10284 *
10285 * On entry:
10286 *  r0 is reentry type, e.g. kInterpEntryInstr (for debugger/profiling)
10287 *  r9 is trampoline PC adjustment *in bytes*
10288 */
10289common_periodicChecks:
10290    ldr     r3, [rGLUE, #offGlue_pSelfSuspendCount] @ r3<- &suspendCount
10291
10292    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
10293    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
10294
10295    ldr     ip, [r3]                    @ ip<- suspendCount (int)
10296
10297    cmp     r1, #0                      @ debugger enabled?
10298    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
10299    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
10300    orrne   ip, ip, r1                  @ ip<- suspendCount | debuggerActive
10301    orrs    ip, ip, r2                  @ ip<- suspend|debugger|profiler; set Z
10302
10303    bxeq    lr                          @ all zero, return
10304
10305    /*
10306     * One or more interesting events have happened.  Figure out what.
10307     *
10308     * If debugging or profiling are compiled in, we need to disambiguate.
10309     *
10310     * r0 still holds the reentry type.
10311     */
10312    ldr     ip, [r3]                    @ ip<- suspendCount (int)
10313    cmp     ip, #0                      @ want suspend?
10314    beq     1f                          @ no, must be debugger/profiler
10315
10316    stmfd   sp!, {r0, lr}               @ preserve r0 and lr
10317#if defined(WITH_JIT)
10318    /*
10319     * Refresh the Jit's cached copy of profile table pointer.  This pointer
10320     * doubles as the Jit's on/off switch.
10321     */
10322    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ r3<-&gDvmJit.pJitProfTable
10323    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
10324    ldr     r3, [r3] @ r3 <- pJitProfTable
10325    EXPORT_PC()                         @ need for precise GC
10326    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh Jit's on/off switch
10327#else
10328    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- glue->self
10329    EXPORT_PC()                         @ need for precise GC
10330#endif
10331    bl      dvmCheckSuspendPending      @ do full check, suspend if necessary
10332    ldmfd   sp!, {r0, lr}               @ restore r0 and lr
10333
10334    /*
10335     * Reload the debugger/profiler enable flags.  We're checking to see
10336     * if either of these got set while we were suspended.
10337     *
10338     * We can't really avoid the #ifdefs here, because the fields don't
10339     * exist when the feature is disabled.
10340     */
10341    ldr     r1, [rGLUE, #offGlue_pDebuggerActive]   @ r1<- &debuggerActive
10342    cmp     r1, #0                      @ debugger enabled?
10343    ldrneb  r1, [r1]                    @ yes, r1<- debuggerActive (boolean)
10344    ldr     r2, [rGLUE, #offGlue_pActiveProfilers]  @ r2<- &activeProfilers
10345    ldr     r2, [r2]                    @ r2<- activeProfilers (int)
10346
10347    orrs    r1, r1, r2
10348    beq     2f
10349
103501:  @ debugger/profiler enabled, bail out; glue->entryPoint was set above
10351    str     r0, [rGLUE, #offGlue_entryPoint]    @ store r0, need for debug/prof
10352    add     rPC, rPC, r9                @ update rPC
10353    mov     r1, #1                      @ "want switch" = true
10354    b       common_gotoBail             @ side exit
10355
103562:
10357    bx      lr                          @ nothing to do, return
10358
10359
10360/*
10361 * The equivalent of "goto bail", this calls through the "bail handler".
10362 *
10363 * State registers will be saved to the "glue" area before bailing.
10364 *
10365 * On entry:
10366 *  r1 is "bool changeInterp", indicating if we want to switch to the
10367 *     other interpreter or just bail all the way out
10368 */
10369common_gotoBail:
10370    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10371    mov     r0, rGLUE                   @ r0<- glue ptr
10372    b       dvmMterpStdBail             @ call(glue, changeInterp)
10373
10374    @add     r1, r1, #1                  @ using (boolean+1)
10375    @add     r0, rGLUE, #offGlue_jmpBuf  @ r0<- &glue->jmpBuf
10376    @bl      _longjmp                    @ does not return
10377    @bl      common_abort
10378
10379
10380/*
10381 * Common code for method invocation with range.
10382 *
10383 * On entry:
10384 *  r0 is "Method* methodToCall", the method we're trying to call
10385 */
10386common_invokeMethodRange:
10387.LinvokeNewRange:
10388    @ prepare to copy args to "outs" area of current frame
10389    movs    r2, rINST, lsr #8           @ r2<- AA (arg count) -- test for zero
10390    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
10391    beq     .LinvokeArgsDone            @ if no args, skip the rest
10392    FETCH(r1, 2)                        @ r1<- CCCC
10393
10394    @ r0=methodToCall, r1=CCCC, r2=count, r10=outs
10395    @ (very few methods have > 10 args; could unroll for common cases)
10396    add     r3, rFP, r1, lsl #2         @ r3<- &fp[CCCC]
10397    sub     r10, r10, r2, lsl #2        @ r10<- "outs" area, for call args
10398    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
103991:  ldr     r1, [r3], #4                @ val = *fp++
10400    subs    r2, r2, #1                  @ count--
10401    str     r1, [r10], #4               @ *outs++ = val
10402    bne     1b                          @ ...while count != 0
10403    ldrh    r3, [r0, #offMethod_outsSize]   @ r3<- methodToCall->outsSize
10404    b       .LinvokeArgsDone
10405
10406/*
10407 * Common code for method invocation without range.
10408 *
10409 * On entry:
10410 *  r0 is "Method* methodToCall", the method we're trying to call
10411 */
10412common_invokeMethodNoRange:
10413.LinvokeNewNoRange:
10414    @ prepare to copy args to "outs" area of current frame
10415    movs    r2, rINST, lsr #12          @ r2<- B (arg count) -- test for zero
10416    SAVEAREA_FROM_FP(r10, rFP)          @ r10<- stack save area
10417    FETCH(r1, 2)                        @ r1<- GFED (load here to hide latency)
10418    ldrh    r9, [r0, #offMethod_registersSize]  @ r9<- methodToCall->regsSize
10419    ldrh    r3, [r0, #offMethod_outsSize]  @ r3<- methodToCall->outsSize
10420    beq     .LinvokeArgsDone
10421
10422    @ r0=methodToCall, r1=GFED, r3=outSize, r2=count, r9=regSize, r10=outs
10423.LinvokeNonRange:
10424    rsb     r2, r2, #5                  @ r2<- 5-r2
10425    add     pc, pc, r2, lsl #4          @ computed goto, 4 instrs each
10426    bl      common_abort                @ (skipped due to ARM prefetch)
104275:  and     ip, rINST, #0x0f00          @ isolate A
10428    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vA (shift right 8, left 2)
10429    mov     r0, r0                      @ nop
10430    str     r2, [r10, #-4]!             @ *--outs = vA
104314:  and     ip, r1, #0xf000             @ isolate G
10432    ldr     r2, [rFP, ip, lsr #10]      @ r2<- vG (shift right 12, left 2)
10433    mov     r0, r0                      @ nop
10434    str     r2, [r10, #-4]!             @ *--outs = vG
104353:  and     ip, r1, #0x0f00             @ isolate F
10436    ldr     r2, [rFP, ip, lsr #6]       @ r2<- vF
10437    mov     r0, r0                      @ nop
10438    str     r2, [r10, #-4]!             @ *--outs = vF
104392:  and     ip, r1, #0x00f0             @ isolate E
10440    ldr     r2, [rFP, ip, lsr #2]       @ r2<- vE
10441    mov     r0, r0                      @ nop
10442    str     r2, [r10, #-4]!             @ *--outs = vE
104431:  and     ip, r1, #0x000f             @ isolate D
10444    ldr     r2, [rFP, ip, lsl #2]       @ r2<- vD
10445    mov     r0, r0                      @ nop
10446    str     r2, [r10, #-4]!             @ *--outs = vD
104470:  @ fall through to .LinvokeArgsDone
10448
10449.LinvokeArgsDone: @ r0=methodToCall, r3=outSize, r9=regSize
10450    ldr     r2, [r0, #offMethod_insns]  @ r2<- method->insns
10451    ldr     rINST, [r0, #offMethod_clazz]  @ rINST<- method->clazz
10452    @ find space for the new stack frame, check for overflow
10453    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- stack save area
10454    sub     r1, r1, r9, lsl #2          @ r1<- newFp (old savearea - regsSize)
10455    SAVEAREA_FROM_FP(r10, r1)           @ r10<- newSaveArea
10456@    bl      common_dumpRegs
10457    ldr     r9, [rGLUE, #offGlue_interpStackEnd]    @ r9<- interpStackEnd
10458    sub     r3, r10, r3, lsl #2         @ r3<- bottom (newsave - outsSize)
10459    cmp     r3, r9                      @ bottom < interpStackEnd?
10460    ldr     r3, [r0, #offMethod_accessFlags] @ r3<- methodToCall->accessFlags
10461    blo     .LstackOverflow             @ yes, this frame will overflow stack
10462
10463    @ set up newSaveArea
10464#ifdef EASY_GDB
10465    SAVEAREA_FROM_FP(ip, rFP)           @ ip<- stack save area
10466    str     ip, [r10, #offStackSaveArea_prevSave]
10467#endif
10468    str     rFP, [r10, #offStackSaveArea_prevFrame]
10469    str     rPC, [r10, #offStackSaveArea_savedPc]
10470#if defined(WITH_JIT)
10471    mov     r9, #0
10472    str     r9, [r10, #offStackSaveArea_returnAddr]
10473#endif
10474    str     r0, [r10, #offStackSaveArea_method]
10475    tst     r3, #ACC_NATIVE
10476    bne     .LinvokeNative
10477
10478    /*
10479    stmfd   sp!, {r0-r3}
10480    bl      common_printNewline
10481    mov     r0, rFP
10482    mov     r1, #0
10483    bl      dvmDumpFp
10484    ldmfd   sp!, {r0-r3}
10485    stmfd   sp!, {r0-r3}
10486    mov     r0, r1
10487    mov     r1, r10
10488    bl      dvmDumpFp
10489    bl      common_printNewline
10490    ldmfd   sp!, {r0-r3}
10491    */
10492
10493    ldrh    r9, [r2]                        @ r9 <- load INST from new PC
10494    ldr     r3, [rINST, #offClassObject_pDvmDex] @ r3<- method->clazz->pDvmDex
10495    mov     rPC, r2                         @ publish new rPC
10496    ldr     r2, [rGLUE, #offGlue_self]      @ r2<- glue->self
10497
10498    @ Update "glue" values for the new method
10499    @ r0=methodToCall, r1=newFp, r2=self, r3=newMethodClass, r9=newINST
10500    str     r0, [rGLUE, #offGlue_method]    @ glue->method = methodToCall
10501    str     r3, [rGLUE, #offGlue_methodClassDex] @ glue->methodClassDex = ...
10502#if defined(WITH_JIT)
10503    GET_JIT_PROF_TABLE(r0)
10504    mov     rFP, r1                         @ fp = newFp
10505    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10506    mov     rINST, r9                       @ publish new rINST
10507    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10508    cmp     r0,#0
10509    bne     common_updateProfile
10510    GOTO_OPCODE(ip)                         @ jump to next instruction
10511#else
10512    mov     rFP, r1                         @ fp = newFp
10513    GET_PREFETCHED_OPCODE(ip, r9)           @ extract prefetched opcode from r9
10514    mov     rINST, r9                       @ publish new rINST
10515    str     r1, [r2, #offThread_curFrame]   @ self->curFrame = newFp
10516    GOTO_OPCODE(ip)                         @ jump to next instruction
10517#endif
10518
10519.LinvokeNative:
10520    @ Prep for the native call
10521    @ r0=methodToCall, r1=newFp, r10=newSaveArea
10522    ldr     r3, [rGLUE, #offGlue_self]      @ r3<- glue->self
10523    ldr     r9, [r3, #offThread_jniLocal_topCookie] @ r9<- thread->localRef->...
10524    str     r1, [r3, #offThread_curFrame]   @ self->curFrame = newFp
10525    str     r9, [r10, #offStackSaveArea_localRefCookie] @newFp->localRefCookie=top
10526    mov     r9, r3                      @ r9<- glue->self (preserve)
10527
10528    mov     r2, r0                      @ r2<- methodToCall
10529    mov     r0, r1                      @ r0<- newFp (points to args)
10530    add     r1, rGLUE, #offGlue_retval  @ r1<- &retval
10531
10532#ifdef ASSIST_DEBUGGER
10533    /* insert fake function header to help gdb find the stack frame */
10534    b       .Lskip
10535    .type   dalvik_mterp, %function
10536dalvik_mterp:
10537    .fnstart
10538    MTERP_ENTRY1
10539    MTERP_ENTRY2
10540.Lskip:
10541#endif
10542
10543    @mov     lr, pc                      @ set return addr
10544    @ldr     pc, [r2, #offMethod_nativeFunc] @ pc<- methodToCall->nativeFunc
10545    LDR_PC_LR "[r2, #offMethod_nativeFunc]"
10546
10547#if defined(WITH_JIT)
10548    ldr     r3, [rGLUE, #offGlue_ppJitProfTable] @ Refresh Jit's on/off status
10549#endif
10550
10551    @ native return; r9=self, r10=newSaveArea
10552    @ equivalent to dvmPopJniLocals
10553    ldr     r0, [r10, #offStackSaveArea_localRefCookie] @ r0<- saved top
10554    ldr     r1, [r9, #offThread_exception] @ check for exception
10555#if defined(WITH_JIT)
10556    ldr     r3, [r3]                    @ r3 <- gDvmJit.pProfTable
10557#endif
10558    str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
10559    cmp     r1, #0                      @ null?
10560    str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
10561#if defined(WITH_JIT)
10562    str     r3, [rGLUE, #offGlue_pJitProfTable] @ refresh cached on/off switch
10563#endif
10564    bne     common_exceptionThrown      @ no, handle exception
10565
10566    FETCH_ADVANCE_INST(3)               @ advance rPC, load rINST
10567    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10568    GOTO_OPCODE(ip)                     @ jump to next instruction
10569
10570.LstackOverflow:    @ r0=methodToCall
10571    mov     r1, r0                      @ r1<- methodToCall
10572    ldr     r0, [rGLUE, #offGlue_self]  @ r0<- self
10573    bl      dvmHandleStackOverflow
10574    b       common_exceptionThrown
10575#ifdef ASSIST_DEBUGGER
10576    .fnend
10577#endif
10578
10579
10580    /*
10581     * Common code for method invocation, calling through "glue code".
10582     *
10583     * TODO: now that we have range and non-range invoke handlers, this
10584     *       needs to be split into two.  Maybe just create entry points
10585     *       that set r9 and jump here?
10586     *
10587     * On entry:
10588     *  r0 is "Method* methodToCall", the method we're trying to call
10589     *  r9 is "bool methodCallRange", indicating if this is a /range variant
10590     */
10591     .if    0
10592.LinvokeOld:
10593    sub     sp, sp, #8                  @ space for args + pad
10594    FETCH(ip, 2)                        @ ip<- FEDC or CCCC
10595    mov     r2, r0                      @ A2<- methodToCall
10596    mov     r0, rGLUE                   @ A0<- glue
10597    SAVE_PC_FP_TO_GLUE()                @ export state to "glue"
10598    mov     r1, r9                      @ A1<- methodCallRange
10599    mov     r3, rINST, lsr #8           @ A3<- AA
10600    str     ip, [sp, #0]                @ A4<- ip
10601    bl      dvmMterp_invokeMethod       @ call the C invokeMethod
10602    add     sp, sp, #8                  @ remove arg area
10603    b       common_resumeAfterGlueCall  @ continue to next instruction
10604    .endif
10605
10606
10607
10608/*
10609 * Common code for handling a return instruction.
10610 *
10611 * This does not return.
10612 */
10613common_returnFromMethod:
10614.LreturnNew:
10615    mov     r0, #kInterpEntryReturn
10616    mov     r9, #0
10617    bl      common_periodicChecks
10618
10619    SAVEAREA_FROM_FP(r0, rFP)           @ r0<- saveArea (old)
10620    ldr     rFP, [r0, #offStackSaveArea_prevFrame] @ fp = saveArea->prevFrame
10621    ldr     r9, [r0, #offStackSaveArea_savedPc] @ r9 = saveArea->savedPc
10622    ldr     r2, [rFP, #(offStackSaveArea_method - sizeofStackSaveArea)]
10623                                        @ r2<- method we're returning to
10624    ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
10625    cmp     r2, #0                      @ is this a break frame?
10626    ldrne   r10, [r2, #offMethod_clazz] @ r10<- method->clazz
10627    mov     r1, #0                      @ "want switch" = false
10628    beq     common_gotoBail             @ break frame, bail out completely
10629
10630    PREFETCH_ADVANCE_INST(rINST, r9, 3) @ advance r9, update new rINST
10631    str     r2, [rGLUE, #offGlue_method]@ glue->method = newSave->method
10632    ldr     r1, [r10, #offClassObject_pDvmDex]   @ r1<- method->clazz->pDvmDex
10633    str     rFP, [r3, #offThread_curFrame]  @ self->curFrame = fp
10634#if defined(WITH_JIT)
10635    ldr     r10, [r0, #offStackSaveArea_returnAddr] @ r10 = saveArea->returnAddr
10636    mov     rPC, r9                     @ publish new rPC
10637    str     r1, [rGLUE, #offGlue_methodClassDex]
10638    str     r10, [r3, #offThread_inJitCodeCache]  @ may return to JIT'ed land
10639    cmp     r10, #0                      @ caller is compiled code
10640    blxne   r10
10641    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10642    GOTO_OPCODE(ip)                     @ jump to next instruction
10643#else
10644    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10645    mov     rPC, r9                     @ publish new rPC
10646    str     r1, [rGLUE, #offGlue_methodClassDex]
10647    GOTO_OPCODE(ip)                     @ jump to next instruction
10648#endif
10649
10650    /*
10651     * Return handling, calls through "glue code".
10652     */
10653     .if    0
10654.LreturnOld:
10655    SAVE_PC_FP_TO_GLUE()                @ export state
10656    mov     r0, rGLUE                   @ arg to function
10657    bl      dvmMterp_returnFromMethod
10658    b       common_resumeAfterGlueCall
10659    .endif
10660
10661
10662/*
10663 * Somebody has thrown an exception.  Handle it.
10664 *
10665 * If the exception processing code returns to us (instead of falling
10666 * out of the interpreter), continue with whatever the next instruction
10667 * now happens to be.
10668 *
10669 * This does not return.
10670 */
10671     .global dvmMterpCommonExceptionThrown
10672dvmMterpCommonExceptionThrown:
10673common_exceptionThrown:
10674.LexceptionNew:
10675    mov     r0, #kInterpEntryThrow
10676    mov     r9, #0
10677    bl      common_periodicChecks
10678
10679    ldr     r10, [rGLUE, #offGlue_self] @ r10<- glue->self
10680    ldr     r9, [r10, #offThread_exception] @ r9<- self->exception
10681    mov     r1, r10                     @ r1<- self
10682    mov     r0, r9                      @ r0<- exception
10683    bl      dvmAddTrackedAlloc          @ don't let the exception be GCed
10684    mov     r3, #0                      @ r3<- NULL
10685    str     r3, [r10, #offThread_exception] @ self->exception = NULL
10686
10687    /* set up args and a local for "&fp" */
10688    /* (str sp, [sp, #-4]!  would be perfect here, but is discouraged) */
10689    str     rFP, [sp, #-4]!             @ *--sp = fp
10690    mov     ip, sp                      @ ip<- &fp
10691    mov     r3, #0                      @ r3<- false
10692    str     ip, [sp, #-4]!              @ *--sp = &fp
10693    ldr     r1, [rGLUE, #offGlue_method] @ r1<- glue->method
10694    mov     r0, r10                     @ r0<- self
10695    ldr     r1, [r1, #offMethod_insns]  @ r1<- method->insns
10696    mov     r2, r9                      @ r2<- exception
10697    sub     r1, rPC, r1                 @ r1<- pc - method->insns
10698    mov     r1, r1, asr #1              @ r1<- offset in code units
10699
10700    /* call, r0 gets catchRelPc (a code-unit offset) */
10701    bl      dvmFindCatchBlock           @ call(self, relPc, exc, scan?, &fp)
10702
10703    /* fix earlier stack overflow if necessary; may trash rFP */
10704    ldrb    r1, [r10, #offThread_stackOverflowed]
10705    cmp     r1, #0                      @ did we overflow earlier?
10706    beq     1f                          @ no, skip ahead
10707    mov     rFP, r0                     @ save relPc result in rFP
10708    mov     r0, r10                     @ r0<- self
10709    mov     r1, r9                      @ r1<- exception
10710    bl      dvmCleanupStackOverflow     @ call(self)
10711    mov     r0, rFP                     @ restore result
107121:
10713
10714    /* update frame pointer and check result from dvmFindCatchBlock */
10715    ldr     rFP, [sp, #4]               @ retrieve the updated rFP
10716    cmp     r0, #0                      @ is catchRelPc < 0?
10717    add     sp, sp, #8                  @ restore stack
10718    bmi     .LnotCaughtLocally
10719
10720    /* adjust locals to match self->curFrame and updated PC */
10721    SAVEAREA_FROM_FP(r1, rFP)           @ r1<- new save area
10722    ldr     r1, [r1, #offStackSaveArea_method] @ r1<- new method
10723    str     r1, [rGLUE, #offGlue_method]    @ glue->method = new method
10724    ldr     r2, [r1, #offMethod_clazz]      @ r2<- method->clazz
10725    ldr     r3, [r1, #offMethod_insns]      @ r3<- method->insns
10726    ldr     r2, [r2, #offClassObject_pDvmDex] @ r2<- method->clazz->pDvmDex
10727    add     rPC, r3, r0, asl #1             @ rPC<- method->insns + catchRelPc
10728    str     r2, [rGLUE, #offGlue_methodClassDex] @ glue->pDvmDex = meth...
10729
10730    /* release the tracked alloc on the exception */
10731    mov     r0, r9                      @ r0<- exception
10732    mov     r1, r10                     @ r1<- self
10733    bl      dvmReleaseTrackedAlloc      @ release the exception
10734
10735    /* restore the exception if the handler wants it */
10736    FETCH_INST()                        @ load rINST from rPC
10737    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10738    cmp     ip, #OP_MOVE_EXCEPTION      @ is it "move-exception"?
10739    streq   r9, [r10, #offThread_exception] @ yes, restore the exception
10740    GOTO_OPCODE(ip)                     @ jump to next instruction
10741
10742.LnotCaughtLocally: @ r9=exception, r10=self
10743    /* fix stack overflow if necessary */
10744    ldrb    r1, [r10, #offThread_stackOverflowed]
10745    cmp     r1, #0                      @ did we overflow earlier?
10746    movne   r0, r10                     @ if yes: r0<- self
10747    movne   r1, r9                      @ if yes: r1<- exception
10748    blne    dvmCleanupStackOverflow     @ if yes: call(self)
10749
10750    @ may want to show "not caught locally" debug messages here
10751#if DVM_SHOW_EXCEPTION >= 2
10752    /* call __android_log_print(prio, tag, format, ...) */
10753    /* "Exception %s from %s:%d not caught locally" */
10754    @ dvmLineNumFromPC(method, pc - method->insns)
10755    ldr     r0, [rGLUE, #offGlue_method]
10756    ldr     r1, [r0, #offMethod_insns]
10757    sub     r1, rPC, r1
10758    asr     r1, r1, #1
10759    bl      dvmLineNumFromPC
10760    str     r0, [sp, #-4]!
10761    @ dvmGetMethodSourceFile(method)
10762    ldr     r0, [rGLUE, #offGlue_method]
10763    bl      dvmGetMethodSourceFile
10764    str     r0, [sp, #-4]!
10765    @ exception->clazz->descriptor
10766    ldr     r3, [r9, #offObject_clazz]
10767    ldr     r3, [r3, #offClassObject_descriptor]
10768    @
10769    ldr     r2, strExceptionNotCaughtLocally
10770    ldr     r1, strLogTag
10771    mov     r0, #3                      @ LOG_DEBUG
10772    bl      __android_log_print
10773#endif
10774    str     r9, [r10, #offThread_exception] @ restore exception
10775    mov     r0, r9                      @ r0<- exception
10776    mov     r1, r10                     @ r1<- self
10777    bl      dvmReleaseTrackedAlloc      @ release the exception
10778    mov     r1, #0                      @ "want switch" = false
10779    b       common_gotoBail             @ bail out
10780
10781
10782    /*
10783     * Exception handling, calls through "glue code".
10784     */
10785    .if     0
10786.LexceptionOld:
10787    SAVE_PC_FP_TO_GLUE()                @ export state
10788    mov     r0, rGLUE                   @ arg to function
10789    bl      dvmMterp_exceptionThrown
10790    b       common_resumeAfterGlueCall
10791    .endif
10792
10793
10794/*
10795 * After returning from a "glued" function, pull out the updated
10796 * values and start executing at the next instruction.
10797 */
10798common_resumeAfterGlueCall:
10799    LOAD_PC_FP_FROM_GLUE()              @ pull rPC and rFP out of glue
10800    FETCH_INST()                        @ load rINST from rPC
10801    GET_INST_OPCODE(ip)                 @ extract opcode from rINST
10802    GOTO_OPCODE(ip)                     @ jump to next instruction
10803
10804/*
10805 * Invalid array index.
10806 */
10807common_errArrayIndex:
10808    EXPORT_PC()
10809    ldr     r0, strArrayIndexException
10810    mov     r1, #0
10811    bl      dvmThrowException
10812    b       common_exceptionThrown
10813
10814/*
10815 * Invalid array value.
10816 */
10817common_errArrayStore:
10818    EXPORT_PC()
10819    ldr     r0, strArrayStoreException
10820    mov     r1, #0
10821    bl      dvmThrowException
10822    b       common_exceptionThrown
10823
10824/*
10825 * Integer divide or mod by zero.
10826 */
10827common_errDivideByZero:
10828    EXPORT_PC()
10829    ldr     r0, strArithmeticException
10830    ldr     r1, strDivideByZero
10831    bl      dvmThrowException
10832    b       common_exceptionThrown
10833
10834/*
10835 * Attempt to allocate an array with a negative size.
10836 */
10837common_errNegativeArraySize:
10838    EXPORT_PC()
10839    ldr     r0, strNegativeArraySizeException
10840    mov     r1, #0
10841    bl      dvmThrowException
10842    b       common_exceptionThrown
10843
10844/*
10845 * Invocation of a non-existent method.
10846 */
10847common_errNoSuchMethod:
10848    EXPORT_PC()
10849    ldr     r0, strNoSuchMethodError
10850    mov     r1, #0
10851    bl      dvmThrowException
10852    b       common_exceptionThrown
10853
10854/*
10855 * We encountered a null object when we weren't expecting one.  We
10856 * export the PC, throw a NullPointerException, and goto the exception
10857 * processing code.
10858 */
10859common_errNullObject:
10860    EXPORT_PC()
10861    ldr     r0, strNullPointerException
10862    mov     r1, #0
10863    bl      dvmThrowException
10864    b       common_exceptionThrown
10865
10866/*
10867 * For debugging, cause an immediate fault.  The source address will
10868 * be in lr (use a bl instruction to jump here).
10869 */
10870common_abort:
10871    ldr     pc, .LdeadFood
10872.LdeadFood:
10873    .word   0xdeadf00d
10874
10875/*
10876 * Spit out a "we were here", preserving all registers.  (The attempt
10877 * to save ip won't work, but we need to save an even number of
10878 * registers for EABI 64-bit stack alignment.)
10879 */
10880    .macro  SQUEAK num
10881common_squeak\num:
10882    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10883    ldr     r0, strSqueak
10884    mov     r1, #\num
10885    bl      printf
10886    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10887    bx      lr
10888    .endm
10889
10890    SQUEAK  0
10891    SQUEAK  1
10892    SQUEAK  2
10893    SQUEAK  3
10894    SQUEAK  4
10895    SQUEAK  5
10896
10897/*
10898 * Spit out the number in r0, preserving registers.
10899 */
10900common_printNum:
10901    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10902    mov     r1, r0
10903    ldr     r0, strSqueak
10904    bl      printf
10905    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10906    bx      lr
10907
10908/*
10909 * Print a newline, preserving registers.
10910 */
10911common_printNewline:
10912    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10913    ldr     r0, strNewline
10914    bl      printf
10915    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10916    bx      lr
10917
10918    /*
10919     * Print the 32-bit quantity in r0 as a hex value, preserving registers.
10920     */
10921common_printHex:
10922    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10923    mov     r1, r0
10924    ldr     r0, strPrintHex
10925    bl      printf
10926    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10927    bx      lr
10928
10929/*
10930 * Print the 64-bit quantity in r0-r1, preserving registers.
10931 */
10932common_printLong:
10933    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10934    mov     r3, r1
10935    mov     r2, r0
10936    ldr     r0, strPrintLong
10937    bl      printf
10938    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10939    bx      lr
10940
10941/*
10942 * Print full method info.  Pass the Method* in r0.  Preserves regs.
10943 */
10944common_printMethod:
10945    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10946    bl      dvmMterpPrintMethod
10947    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10948    bx      lr
10949
10950/*
10951 * Call a C helper function that dumps regs and possibly some
10952 * additional info.  Requires the C function to be compiled in.
10953 */
10954    .if     0
10955common_dumpRegs:
10956    stmfd   sp!, {r0, r1, r2, r3, ip, lr}
10957    bl      dvmMterpDumpArmRegs
10958    ldmfd   sp!, {r0, r1, r2, r3, ip, lr}
10959    bx      lr
10960    .endif
10961
10962#if 0
10963/*
10964 * Experiment on VFP mode.
10965 *
10966 * uint32_t setFPSCR(uint32_t val, uint32_t mask)
10967 *
10968 * Updates the bits specified by "mask", setting them to the values in "val".
10969 */
10970setFPSCR:
10971    and     r0, r0, r1                  @ make sure no stray bits are set
10972    fmrx    r2, fpscr                   @ get VFP reg
10973    mvn     r1, r1                      @ bit-invert mask
10974    and     r2, r2, r1                  @ clear masked bits
10975    orr     r2, r2, r0                  @ set specified bits
10976    fmxr    fpscr, r2                   @ set VFP reg
10977    mov     r0, r2                      @ return new value
10978    bx      lr
10979
10980    .align  2
10981    .global dvmConfigureFP
10982    .type   dvmConfigureFP, %function
10983dvmConfigureFP:
10984    stmfd   sp!, {ip, lr}
10985    /* 0x03000000 sets DN/FZ */
10986    /* 0x00009f00 clears the six exception enable flags */
10987    bl      common_squeak0
10988    mov     r0, #0x03000000             @ r0<- 0x03000000
10989    add     r1, r0, #0x9f00             @ r1<- 0x03009f00
10990    bl      setFPSCR
10991    ldmfd   sp!, {ip, pc}
10992#endif
10993
10994
10995/*
10996 * String references, must be close to the code that uses them.
10997 */
10998    .align  2
10999strArithmeticException:
11000    .word   .LstrArithmeticException
11001strArrayIndexException:
11002    .word   .LstrArrayIndexException
11003strArrayStoreException:
11004    .word   .LstrArrayStoreException
11005strDivideByZero:
11006    .word   .LstrDivideByZero
11007strNegativeArraySizeException:
11008    .word   .LstrNegativeArraySizeException
11009strNoSuchMethodError:
11010    .word   .LstrNoSuchMethodError
11011strNullPointerException:
11012    .word   .LstrNullPointerException
11013
11014strLogTag:
11015    .word   .LstrLogTag
11016strExceptionNotCaughtLocally:
11017    .word   .LstrExceptionNotCaughtLocally
11018
11019strNewline:
11020    .word   .LstrNewline
11021strSqueak:
11022    .word   .LstrSqueak
11023strPrintHex:
11024    .word   .LstrPrintHex
11025strPrintLong:
11026    .word   .LstrPrintLong
11027
11028/*
11029 * Zero-terminated ASCII string data.
11030 *
11031 * On ARM we have two choices: do like gcc does, and LDR from a .word
11032 * with the address, or use an ADR pseudo-op to get the address
11033 * directly.  ADR saves 4 bytes and an indirection, but it's using a
11034 * PC-relative addressing mode and hence has a limited range, which
11035 * makes it not work well with mergeable string sections.
11036 */
11037    .section .rodata.str1.4,"aMS",%progbits,1
11038
11039.LstrBadEntryPoint:
11040    .asciz  "Bad entry point %d\n"
11041.LstrArithmeticException:
11042    .asciz  "Ljava/lang/ArithmeticException;"
11043.LstrArrayIndexException:
11044    .asciz  "Ljava/lang/ArrayIndexOutOfBoundsException;"
11045.LstrArrayStoreException:
11046    .asciz  "Ljava/lang/ArrayStoreException;"
11047.LstrClassCastException:
11048    .asciz  "Ljava/lang/ClassCastException;"
11049.LstrDivideByZero:
11050    .asciz  "divide by zero"
11051.LstrFilledNewArrayNotImpl:
11052    .asciz  "filled-new-array only implemented for objects and 'int'"
11053.LstrInternalError:
11054    .asciz  "Ljava/lang/InternalError;"
11055.LstrInstantiationError:
11056    .asciz  "Ljava/lang/InstantiationError;"
11057.LstrNegativeArraySizeException:
11058    .asciz  "Ljava/lang/NegativeArraySizeException;"
11059.LstrNoSuchMethodError:
11060    .asciz  "Ljava/lang/NoSuchMethodError;"
11061.LstrNullPointerException:
11062    .asciz  "Ljava/lang/NullPointerException;"
11063
11064.LstrLogTag:
11065    .asciz  "mterp"
11066.LstrExceptionNotCaughtLocally:
11067    .asciz  "Exception %s from %s:%d not caught locally\n"
11068
11069.LstrNewline:
11070    .asciz  "\n"
11071.LstrSqueak:
11072    .asciz  "<%d>"
11073.LstrPrintHex:
11074    .asciz  "<0x%x>"
11075.LstrPrintLong:
11076    .asciz  "<%lld>"
11077
11078